skip to Main Content

The following figure points to the current UI:

Initial UI|

The given HTML and CSS code:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <title>Flexbox example page</title>
    <link href="styles.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <nav>
      <ul class="site-nav">
        <li><a href="#">Home</a></li>
        <li><a href="#">Features</a></li>
        <li><a href="#">Pricing</a></li>
        <li><a href="#">Support</a></li>
        <li class="nav-right"><a href="#">About</a></li>
      </ul>
    </nav>
  </body>
</html>
*,
::before,
::after {
  box-sizing: border-box;
}
body {
  margin: unset;
  background-color: #709b90;
  font-family: Helvetica, Arial, sans-serif;
}
.site-nav {
  display: flex;
  padding: 0.5rem;
  list-style-type: none;
  background: #5f4b44;
}
.site-nav > li > a {
  text-decoration: none;
  color: white;
  background: #cc6b5a;
  padding: 0.5em 1em;
}

The original problem arises after applying the following CSS:

.site-nav > li > a {
  display: block;
}

The resulting UI:

Resulted UI

The resulting UI is expected for me, but I can’t figure out how the CSS works here.

NOTE I tried dev tooling, and it appears that the block value causes the element to take the entire width of its parent, introducing a line break. This increases the height of the nav item’s content to 1px.

Now, my concern is,

  1. How does the display: block property affect the UI? (i.e. After adding the block value, the padding of the li element increases automatically!)
  2. What’s the underlying idea here that I couldn’t figure out?
  3. Is there any deep understanding that I’m missing?

3

Answers


  1. function f(){
      document.querySelectorAll('.site-nav > li > a')
        .forEach( el => {
          el.classList.toggle('block');
        });
    }
    *,
    ::before,
    ::after {
      box-sizing: border-box;
    }
    body {
      margin: unset;
      background-color: #709b90;
      font-family: Helvetica, Arial, sans-serif;
    }
    .site-nav {
      display: flex;
      padding: 0.5rem;
      list-style-type: none;
      background: #5f4b44;
    }
    .site-nav > li > a {
      text-decoration: none;
      color: white;
      background: #cc6b5a;
      padding: 0.5em 1em;
    }
    
    /*.site-nav > li > a,*/
    .block {
      display: block;
    }
    <!DOCTYPE html>
    <html lang="en-US">
      <head>
        <title>Flexbox example page</title>
        <link href="styles.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <nav>
          <ul class="site-nav">
            <li><a href="#">Home</a></li>
            <li><a href="#">Features</a></li>
            <li><a href="#">Pricing</a></li>
            <li><a href="#">Support</a></li>
            <li class="nav-right"><a href="#">About</a></li>
          </ul>
        </nav>
        
        <button onclick="f();">asdf</button>
      </body>
    </html>
    Login or Signup to reply.
  2. display: block vs. inline

    In the snippet I created below, I think you’ll get a better picture of what is happening when you add display: block;. I have added inline styling to only a few of the <a> tags to better illustrate the difference between the display: block; and the default display: inline;.

    The first, third and fifth <a> tags are showing the display: block; behaviour, which is to take up the space they occupy as though they have rigid containers.

    The second and fourth <a> tags are showing the display: inline; behaviour, which is that they don’t take up an entire space, but rather, live within the space they have been placed within.

    *,
    ::before,
    ::after {
      box-sizing: border-box;
    }
    body {
      margin: unset;
      background-color: #709b90;
      font-family: Helvetica, Arial, sans-serif;
    }
    .site-nav {
      display: flex;
      padding: 0.5rem;
      list-style-type: none;
      background: #5f4b44;
    }
    .site-nav > li > a {
      text-decoration: none;
      color: white;
      background: #cc6b5a;
      padding: 0.5em 1em;
    }
    <!DOCTYPE html>
    <html lang="en-US">
      <head>
        <title>Flexbox example page</title>
        <link href="styles.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <nav>
          <ul class="site-nav">
            <li><a style="display: block;" href="#">Home</a></li>
            <li><a href="#">Features</a></li>
            <li><a style="display: block;" href="#">Pricing</a></li>
            <li><a href="#">Support</a></li>
            <li class="nav-right"><a style="display: block;" href="#">About</a></li>
          </ul>
        </nav>
      </body>
    </html>

    I think this summary generally answers all three of your questions, but let me know if further clarification is needed.

    Login or Signup to reply.
  3. TL;DR: Only inline-axis sizes are respected for inline boxes in inline formatting contexts; block-axis sizes are ignored.


    CSS Display 3 includes an informative table for display, where it lists:

    Short display Full display Generated box
    inline inline flow inline box

    Such an inline box is defined as:

    A non-replaced inline-level box
    whose inner display type is ‘flow’.
    The contents of an inline box participate
    in the same inline formatting context as the inline box itself.

    Where ‘flow’ is defined as:

    The element lays out its contents
    using flow layout (block-and-inline layout).

    If its outer display type is ‘inline’ …,
    and it is participating in a block or inline formatting context,
    then it generates an inline box.

    The linked "block-and-inline layout" definition is a bit outdated, but it reads (in 9.4.2 Inline formatting contexts of CSS 2.1):

    Horizontal margins, borders, and padding are respected between these boxes.

    A more up-to-date resource would be 2. Inline Layout Model of CSS Inline 3, though it basically states the same:

    In an inline formatting context, content is laid out
    along the inline axis, … . Inline-axis margins, borders, and padding
    are respected between inline-level boxes … .

    This effectively means that block-axis sizes are ignored in these cases.

    Example:

    p {
      border: 1px solid blue;
      overflow: hidden;
      resize: both;
    }
    
    span {
      border: 1px dashed red;
      padding-block: .8em;
    }
    <p>
      <span>Try</span> resizing the <code>&lt;p&gt;</code> element!
      <span>This</span> is some inline-level content
      with several <code>&lt;span&gt;</code>s <span>throughout</span>,
      to see their block-axis sizes being <span>ignored</span>.
    </p>

    By changing from inline to block, the block-axis margins, borders and paddings will be respected as well: The a elements will push out the block-axis size of the ancestor .site-nav, instead of overlapping the ancestor’s padding.


    I believe the extra 1px at the bottom comes vertical-align being baseline by default, incidentally overlapping the top. (Read more about vertical-align in this answer.)

    Example comparing vertical-align: baseline and middle:

    div {
      padding-block: .5em;
      background-color: cornflowerblue;
    }
    
    span {
      padding-block: .5em;
      background-color: lightpink;
    }
    
    #inline-middle span {
      vertical-align: middle;
    }
    #block span {
      display: block;
    }
    <figure id="inline">
      <div>
        <span>TEXT</span>
      </div>
      <caption><code>&lt;div&gt;</code> with inline-level <code>&lt;span&gt;</code></caption>
    </figure>
    
    <figure id="inline-middle">
      <div>
        <span>TEXT</span>
      </div>
      <caption>
        <code>&lt;div&gt;</code> with inline-level <code>&lt;span&gt;</code> aligned to middle
      </caption>
    </figure>
    
    <figure id="block">
      <div>
        <span>TEXT</span>
      </div>
      <caption><code>&lt;div&gt;</code> with block-level <code>&lt;span&gt;</code></caption>
    </figure>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search