skip to Main Content

Why are "Foo" and "Bar" not aligned vertically in my example?

If I stop hiding the overflow from the parent of "Bar" (click the button) – suddenly the overflowed element "Baz" does align with "Foo".

When overflowed, "Foo" and "Bar" have the exact same height when inspected, they are simply rendered at a different height and I can’t figure out why.

The JS is not relevant, just helps demonstrate the problem.

const target = document.querySelector("#second")
const button = document.querySelector("button")

toggle = true
button.addEventListener("click", () => {
  if (toggle) {
    target.style.overflow = "initial"
  } else {
    target.style.overflow = "hidden"
  }
  toggle = !toggle
})
* {
  margin: 0;
  padding: 0;
  line-height: 1em;
  box-sizing: border-box;
}
main {
  background: #eee;
  padding: 1em;
  font-size: 8vw;
}
#first {
  background: red;
  display:inline-block;
  height: 1em;
}
#second {
  background: blue;
  display:inline-block;
  height: 1em;
  overflow: hidden;
}
<button>Toggle overflow for #second</button>
<main>
  <span id="first">
    FOO[
  </span><span id="second">
    <div>]BAR</div>
    <div>]BAZ</div>
  </span>  
</main>

2

Answers


  1. Ok, so looking at your example. I think you can solve this with flex containers. for sure you can cleanup this a bit. But this removes the need to correct the alignment with margin.

    * {
      margin: 0;
      padding: 0;
      line-height: 1em;
    }
    
    /* To help understand what is going on, uncomment below - note that this does slighty break the animation */
    /*
    { border: 0.1vw solid red; }
    */
    
    body {
      display: grid;
      place-items: center;
      margin: 0;
      height: 80vh;
      background: lightpink;
    }
    
    .container {
      background: white;
      font-size: 5vw; /* This determines the main size! */
      padding: 1em;
      display: flex;
    }
    .before {
      display: flex;
      height: 1.5em;
      align-items: center;
    }
    .animate {
      display: flex;
      flex-direction: column;
      height: 1.5em;
      overflow: hidden;
      position: relative;
    
    }
    .animate span {
      background:lightpink;
      display: flex;
      flex-direction: column;
      position: relative;
      line-height: 1.5em;
      animation: scroll 6s infinite linear;
    }
    @keyframes scroll {
      /* Found with experimentation, not math */
      0% { top: -4.48em } 
      100% { top: -9em; }
    }
    

    Here a codepen

    Login or Signup to reply.
  2. Those are inline-blocks which by default are aligned along their baseline. Add vertical-align: top; and you’ll be set:

    const target = document.querySelector("#second")
    const button = document.querySelector("button")
    
    toggle = true
    button.addEventListener("click", () => {
      if (toggle) {
        target.style.overflow = "initial"
      } else {
        target.style.overflow = "hidden"
      }
      toggle = !toggle
    })
    * {
      margin: 0;
      padding: 0;
      line-height: 1em;
      box-sizing: border-box;
    }
    main {
      background: #eee;
      padding: 1em;
      font-size: 8vw;
    }
    #first {
      background: red;
      display:inline-block;
      height: 1em;
    }
    #second {
      background: blue;
      display:inline-block;
      height: 1em;
      overflow: hidden;
      vertical-align: top;
    }
    <button>Toggle overflow for #second</button>
    <main>
      <span id="first">
        FOO[
      </span><span id="second">
        <div>]BAR</div>
        <div>]BAZ</div>
      </span>  
    </main>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search