LaunchCode logo
  1. Contents
  2. 22. Refill the Flask
  3. 22.7. Page Navigation

22.7. Page Navigation¶

So far, we’ve used the address bar in the browser to access each webpage we’ve built. However, we need to do better than this. Users shouldn’t have to type in the address for every page they want to visit!

Adding links that connect to other pages in our website makes navigation much easier. These links can take many forms, like a simple list of URLs, a set of clickable icons, Next Page and Previous Page buttons, a dropdown menu, or a nav bar. (You can find several of these options on this page!)

22.7.1. A List of Links¶

Let’s start with a basic, unordered list of links. Each item will lead to one of the pages in our website. For now, we will keep the design simple. We can make it look nice after we get the navigation working.

Since we want the list to appear on every page, we will add it to the base template.

  1. Open base.html in Visual Studio Code.

  2. Add a nav element below the endblock statement. Include a heading and an unordered list. Make one item for each of the pages you created earlier.

    15
    16
    17
    18
    19
    20
    21
    <nav>
       <h3>Page Navigation</h3>
       <ul>
          <li>Pizza Topping Form</li>
          <li>Second Page</li>
       </ul>
    </nav>
    

    Save your work, then launch main.py. The list should appear on each page that extends base.html.

  3. Next, change the list items from text to active links.

    1. Wrap the text in link tags, <a></a>.

      <li><a href="">Pizza Topping Form</a></li>
      <li><a href="">Second Page</a></li>
      
    2. Fill in the href values with the path to each page:

      <li><a href="/">Pizza Topping Form</a></li>
      <li><a href="/second">Second Page</a></li>
      

    Note the values assigned to each href. The strings match the paths from the @app.route() handlers in main.py. They should NOT be the .html names you gave to the template files. The paths you use will depend on your Python code. They might not match this example.

  4. Save your work, then refresh the tab in the browser. Properly done, the navigation links should work something like this:

    Clicking either of the two links in the list navigates to the chosen page.

    A list of links provides basic website navigation.¶

Try It!

If we hover the pointer over one of the links, its URL appears in the bottom corner of the browser window.

Hovering over a link displays the target URL in the lower corner of the browser window.

22.7.2. Bring in Some Logic¶

So far, so good. The list of links works. However, there is a weakness in our code. If we add, remove, or rearrange the pages in our website, we need to manually adjust the li elements in base.html. It would be better if the size and order of the list automatically updates when we make a change.

Fortunately, we make this happen by adding a for loop to the base template. Since each link requires two pieces of data (an href value and the link text), we have a few options for feeding this information from Python to the templates. Three possibilities are a list of lists, a dictionary, or an object created from a user-defined class. (There are other choices as well).

In this case, we will use a dictionary.

22.7.2.1. Update main.py¶

  1. Near the top of the code in main.py, define a dictionary called navigation.

  2. Add one key/value pair for each page in your website. The key will be the text for the link. The value will be the path to that page.

    3
    4
    5
    6
    7
    8
    9
    app = Flask(__name__)
    app.config['DEBUG'] = True
    
    navigation = {
       'Pizza Toppings Form': '/',
       'Second Page': '/second'
    }
    
  3. Include the navigation dictionary as an argument in each render_template() function.

    return render_template('template_name', navigation = navigation, ...)
    

22.7.2.2. Update base.html¶

Jinja3 uses the same syntax as Python to loop through a dictionary by key/value paris.

  1. Replace the li items in the list with a loop:

    15
    16
    17
    18
    19
    20
    21
    22
    <nav>
       <h3>Page Navigation</h3>
       <ul>
          {% for (text, path) in navigation.items() %}
             <li><a href={{path}}>{{text}}</a></li>
          {% endfor %}
       </ul>
    </nav>
    
  2. Each time the loops runs, text is assigned the next key in the dictionary. path takes the value of that key.

  3. Save your work, then refresh the tab in the browser. Test to make sure both links still work.

Try It!

With the loop in place, changes made to navigation will appear on all pages that extend base.html. Test this out!

  1. Try rearranging the order of the key/value pairs in navigation.

  2. Add a third page to the website. Include a key/value pair for the page in the navigation dictionary.

22.7.3. A Dropdown Menu¶

As a website grows, the navigation menu requires more space on the page. To keep their layout neat and consistent, web developers often use features that hide the menu until a user reveals it.

A dropdown menu appears when the cursor hovers over a heading.

Menu items appear when the user hovers over a each heading.¶

While it won’t be as fancy as the image, we can add some CSS rules to make our own dropdown menu. It will appear when the user moves their pointer over the Page Navigation heading.

  1. First, add the following class attributes to the <nav>, <h3>, and <ul> tags:

    15
    16
    17
    18
    19
    20
    21
    22
    <nav class="dropdown">
       <h3 class="droptitle">Page Navigation</h3>
       <ul class="dropdown-content">
          {% for (text, path) in navigation.items() %}
             <li><a href={{path}}>{{text}}</a></li>
          {% endfor %}
       </ul>
    </nav>
    
  2. Next, add the following class selectors to style.css. The explanation for how the code works follows this section.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    .dropdown {
       position: relative;
    }
    
    .droptitle {
       margin-bottom: 0px;
    }
    
    .dropdown-content {
       display: none;  /* Hides content */
       position: absolute;
       margin-top: 0px;
       background-color: white;
       width: 100%;
       border: 1px solid lightgray;
       padding: 10px 15px;
    }
    
    .dropdown:hover .dropdown-content {
       display: block;  /* Displays content */
    }
    
  3. Save, then use Shift + Refresh or Control + Refresh to apply the CSS changes in the browser. Move the cursor over the heading to test the code.

    A dropdown menu showing a 3-item unordered list.

    Yay! A working dropdown menu!¶

22.7.3.1. CSS Breakdown¶

Let’s take a look at how the CSS rules make a working dropdown.

  1. Line 2: position: relative makes the elements inside the <nav></nav> tags pair up with each other. The h3 comes first, with the ul right below it.

  2. Line 11: When the dropdown items appear, position: absolute makes them overlap other content instead of pushing it further down the page. The revealed menu covers up other text and images. If we set this value to relative, then anything below the menu would shift position when it opens.

  3. Lines 6 & 12: For dropdown menus, we need to be careful with margins. If the gap between the label and the choices is too large, then the content will disappear when the user moves their mouse to make a selection! To prevent this, we set the bottom margin of droptitle to zero pixels. Similarly, we set the top margin of dropdown-content to 0px.

  4. Lines 13-16: These properties control the appearance of the menu.

    1. Setting a background-color hides any content that the menu overlaps when it opens.

    2. width: 100% makes the menu take up the same horizontal space as its container (nav).

    3. border and padding make the menu area and text more obvious.

  5. Line 10: display: none hides the element from the screen. The menu items are still on the page, but they do not appear in the view.

  6. Lines 19-21: .dropdown:hover .dropdown-content controls the operation of the menu. In the browser, when the pointer moves over the nav element, dropdown:hover becomes True. When this happens, display: block is applied to the dropdown-content class. This overrules the display: none statement in line 10, and the menu appears on the page! When the pointer moves away from the menu, dropdown:hover becomes False, and display: none is reapplied.

Tip

You can explore other dropdown styling options at W3Schools.

22.7.4. Navigation Bar and Other Options¶

There are LOTS of ways to create smooth website navigation. While we won’t dive any deeper into this topic, here are a few helpful resources you can explore on your own.

Down the Rabbit Hole:

  1. CSS Navbar at W3Schools.

  2. Navs & tabs, Navbar, and Pagination components at Bootstrap.

  3. Flask-Menu is an extension that adds support for generating menus.

  • ← 22.6. Reusing Content
  • 22.8. Redirecting →

Back to top

Page Source