javascripthtmlcss

Use of Template for Common html/css Format Across Site


Im working on a website and I am relatively new to this. I've made a homepage with a navbar & header, and a handful of pages that can be navigated to.

Everything works, but when I look at the source code, I feel frustrated at the shear redundancy of having all the metadata in the header, very nested nav bar drop down menu, and other repeated content in every html file.

Is there a way to create a template, or break down these very densely nested elements into their own files, so that when I want to put them in my markup, I can use a reference to that file rather than all this code? or should I consider this a non-issue and move on?

I feel like this solution I'm thinking of would involve a function and JS. If yes, would this be an ideal solution, considering by default some people disable JS in their browsers?

note: I usually work in python, where I enjoy writing things that work, but are very neat and short. I suspect that this inclination is fading into my web development and making me want to opt out of inelegant solutions when and where they are effective.

Here is index.html for reference:


<!DOCTYPE>
<html lang="en" dir="ltr" class="no-js">
     <head> 
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=Edge">
          <meta http-equiv="content-language" content="en-us">
        <meta name="author" content="*********">
            <meta name="viewport" content="width=device-width,minimum-scale=1">
        <meta name="robots" content="noindex,nofollow">
          <title>IVDb~ The hogspot sausage Database</title>
          <link rel="stylesheet" href="stylesheet.css">
     </head>
     <body>
          <div id="header">
               <a href="index.html"><img id="logo" src="logo.png" alt="the hogspot sausage Database logo"></img></a>
               <input id="searchbar" type="text"><button>Search</button><a href="sign_in.html"><button>Sign in</button></a>
          </div>
               <nav>
                    <ul id="menu">
                         <li><a href="watchlist.html">Watchlist</a>
                              <ul id="sub-menu">
                                   <li><a href="#New">New Releases</a></li>
                                   <li><a href="#Pop">Popular Sausages</a></li>
                                   <li><a href="#Highly">Highly Rated</a></li>
                                   <li><a href="#Recent">Recent</a></li>             
                              </ul>
                         </li>
                         <li><a href="forum.html">Forum</a>
                              <ul id="sub-menu">
                                        <li><a href="#">Just Posted</a></li>
                                        <li><a href="#">Hot Threads</a></li>
                                        <li><a href="#">Admin Favorites</a></li>
                                        <li><a href="#">Beansprout</a></li>          
                              </ul>
                         </li>
                         <li><a href="reccomendations.html">Reccomendations</a>
                              <ul id="sub-menu">
                                        <li><a href="#">This Week's Select Sausages</a></li>
                                        <li><a href="#">Browse Topics</a></li>
                                        <li><a href="#">Well traveled reviews</a></li>
                                        <li><a href="#">this Month</a></li>          
                                   </ul>
                         </li>
                         <li><a href="games.html">Sausages</a>
                              <ul id="sub-menu">
                                   <li><a href="#">Platformer</a></li>
                                   <li><a href="#">RPG</a></li>
                                   <li><a href="#">Combat</a></li>
                                   <li><a href="#">Sports</a></li>          
                              </ul>
                         </li>
                         <li><a id="r1" href="rate.html">Rate it!</a>
                              <ul id="sub-menu">
                                   <li><a href="#">Submit a rating or review</a></li>
                                   <li><a href="#">Search existing</a></li>          
                              </ul>
                         </li>
                    </ul>
               </nav>
          <div id="cycle">
               <!--9/19 should put each image in a figure tag with rate and buy button/links aligned directly below--->
               <img id="first" src="">
               <img src="">
               <img src="">
          </div>
          <h2>Latest News</h2>
          <div id="blog">
               <div class="mySlides">
                    <div class="numbertext">1 / 3</div>
                    <img src="videogames\game5.jpg" style="width:100%">
                    <div class="text">some content</div>
               </div>           
               <div class="mySlides">
                    <div class="numbertext">2 / 3</div>
                    <img src="videogames\game4.jpg" style="width:100%">
                    <div class="text">some content</div>
               </div>
               <div class="mySlides">
                    <div class="numbertext">3 / 3</div>
                    <img src="videogames\game10.jpg" style="width:100%">
                    <div class="text">some content</div>
               </div>           
               <!-- Next and previous buttons -->
               <!--took them out cause they were messing with my css-->
          </div>
          <br>
          <!-- The dots/circles -->
          <div style="text-align:center">
               <span class="dot" onclick="currentSlide(1)"></span>
               <span class="dot" onclick="currentSlide(2)"></span>
               <span class="dot" onclick="currentSlide(3)"></span>
          </div>     
          </div>
          <h2>Just Released</h2>
          <div id="cycle">
               <img id="first" src="">
               <img src="">
               <img src="">
          </div>
          <footer>
               Legal stuff: copyright <br>
               social media icons <br>
               other footer details <br>
          </footer>
     </body>
</html>

and another page in the site:

<html lang="en" dir="ltr" class="no-js">
     <head>
       metadata here
       <link rel="stylesheet" href="stylesheet.css">
     </head>
     <body>
             <nav>drop down menu here  </nav>
          <h4>Create an account by entering your info below</h4>
          <form action="POST">
           <!----we should use css to center-align these input fields, rather than &nbsp----->
               Full name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text"><br>
               User name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" name="" id=""><br>
               Email Address&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" name="" id=""><br>
               Password&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text"><br>
               Confirm Password&nbsp;<input type="text"><br>
               <button>Submit</button>
          </form>
     </body>
</html>


Solution

  • There are two strategies you could use to solve your problem. They both come with their pros and cons, but they primarily depend upon one question: are you using a bundler or not?

    Using an external HTML file as a template and injecting it into the page

    One of the approaches could be to write a template file, requesting it via javascript and then injecting it into the DOM. The problem with this method is that you have to set up / your server to have this useless static page available through a request, but then you could easily create subdirectories like /static/templates/navbar.html.

    This is a short example of this approach:

    fetch('/static/templates/navbar.html').then(response => {
       if(response.ok)
          return response.txt();
    }).then(page => {
        document.body.innerHTML += page;
    });
    

    The obvious limitations of this method are that you need to create an HTML template file for every component and load them in order, otherwise, your DOM will be a mess (1), and then you will need to download all these templates that will require additional bandwidth.

    Refactoring your tags via javascript and injecting them into the page

    In case you are using a bundler, I honestly think this approach is more sustainable as you are not requesting any other file, instead, you can create these elements via javascript and then load them via another script. The script will contain a function (something like init() or similar) that will inject the elements into the DOM.

    const nav = document.createElement('nav');
    const ul = document.createElement('ul');
    ul.id = 'menu';
    const li01 = document.createElement('li');
    const a01 = document.createElement('a');
    a01.href = 'watchlist.html';
    a01.innerText = 'Watchlist';
    li01.appendChild(a01);
    ul.appendChild(li01);
    nav.appendChild(ul);
    

    And from here you can understand how it works. The good thing about this approach is that you don't need to request any external file and that you can write all this code inside another file that the bundler will automatically compile into a single .js (2). On the other hand, if your menu is huge your time to interactive might peak up due to all the javascript calculations.

    Use a javascript framework

    As already stated from another user, there are different frameworks that are being used that allow you to create templates called components and then load them dynamically, such as React, Preact, VueJS, Angular and many others. Learning at least one of these will absolutely help you in case you want to look for a job in web development. The downside of this approach is that you're basically injecting a lot of functions that you may never use into your code, which will obviously be slower compared to vanilla javascript.

    Take your pick!

    (1) remember that fetch is an asynchronous function, and therefore it doesn't load assets in order. (2) in case for some reason you don't want to use a bundler, you could still load the file via another script tag.