skip to Main Content

Here is what my HTML looks like:

<html>
  <body>
    <header>...</header>
    <main>...</main>
  </body>
</html>

My header does not have a declared height, but it has content in it that makes it take up about 10% of the screen vh.

I want to be able to set the body tag to 100vh and then set the main tag to 100% so that I can center the content of the main tag to be in the center of that part of the screen.

Instead, what happens is the main tag height becomes like another 100vh under the header, so you have to scroll down to get to the bottom of the main tag.

I don’t want that to happen. I just want the main tag to fill the height of the parent body tag which stops at the bottom of the screen. I do NOT want to have to scroll down to get to the bottom of the main tag. I just want to center one sentence on the screen. Instead, it looks like the text is closer to the bottom of the screen, not centered, because the main tag reaches below the bottom of the screen.

How would I style the html page to make the main tag only fill the height of the body tag and nothing more?

3

Answers


  1. Your problem is that when you set main {height: 100%;}, the percentage refers to the containing block, which is the body itself.

    To achieve what you want, style the body as a flexbox and allow main to grow.

    html, body {
      height: 100%;
      margin: 0;
    }
    body {
      display: flex;
      flex-direction: column;
      border: 10px solid red;
      box-sizing: border-box;
    }
    header {
      background: lime;
    }
    main {
      background: cyan;
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    <body>
      <header>A<br>B<br>C<br></header>
      <main>Content</main>
    </body>
    Login or Signup to reply.
  2. @BrettDonald’s solution is good; I originally read your question as you wanted to center the text in the screen, NOT in the <main> tag, which will involve some kind of absolute or fixed position for your scrollbar. Upon re-reading the question, I’m still not sure exactly what you are searching for, but I already made this example to center the text on the screen, rather than in the <main> tag, so here you go.

    header{
      position: absolute;
      padding-top: 20px;
      top: 0;
      width: 100%;
      height: 50px;
      text-align: center;
      background: lightblue;
    }
    
    main{
      height: 100vh;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    body{
      position: relative;
      height: 100vh;
    }
    
    *{
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    <html>
      <body>
        <header>header content</header>
        <main>
          <text>this sentence should be centered</text>
        </main>
      </body>
    </html>
    Login or Signup to reply.
  3. Remaining space

    To make <main> take up the remaining space of <body>, you can use:

    CSS Grid

    CSS Grid allows us to define a grid layout and distribute space. By declaring <header>‘s row height to auto, we can assign <main>‘s row the remaining height with flexible lengths (fr):

    body {
      height: 100vh;
      display: grid;
      grid-template-rows: auto 1fr;
    }
    
    /*Ignore; for demonstrational purposes*/
    body {margin: 0}
    header {
      height: 2rem;
      background-color: red;
    }
    main {
      background-color: blue;
    }
    <body>
      <header></header>
      <main></main>
    </body>

    Flexbox

    Flexbox allows us to lay out flex children along a main axis. We can let a child grow to fill that axis with the flex-grow property:

    body {
      height: 100vh;
      display: flex;
      flex-direction: column;
    }
    main {flex-grow: 1}
    
    /*Ignore; for demonstrational purposes*/
    body {margin: 0}
    header {
      height: 2rem;
      background-color: red;
    }
    main {background-color: blue}
    <body>
      <header></header>
      <main></main>
    </body>

    Centering text

    The large and prominent section "above the fold" is commonly called hero section, hero banner or similar.

    When placing an out-of-flow header onto the hero section, then centering can be done by absolute positioning then translating.

    Note: With above, make sure not to place any (hero) content behind the header!

    Centering may become tricky if the hero section is not the same size as the viewport but you still want its content to be centered to the viewport.

    When centering with CSS Grid and place-items: center, then content is only centered to its parent but not to the viewport:

    body {
      height: 100vh;
      display: grid;
      grid-template-rows: auto 1fr;
    }
    header {height: 4rem}
    #hero {
      height: 100%;
      display: grid;
      place-items: center;
    }
    
    /*Ignore; for demonstrational purposes*/
    body {margin: 0}
    header {background-color: lightpink}
    main {background-color: lightblue}
    
    /*Center cross*/
    body::before, body::after {
      content: "";
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: black;
    }
    body::before {
      width: 2rem;
      height: 2px;
    }
    body::after {
      width: 2px;
      height: 2rem;
    }
    <body>
      <header></header>
      <main>
        <section id=hero>
          <span id=hero-content>Hero content</span>
        </section>
      </main>
    </body>

    But if we know the header’s (absolute) height then we can take it into account:

    body {
      --header-height: 4rem;
      height: 100vh;
      display: grid;
      grid-template-rows: auto 1fr;
    }
    header {height: var(--header-height)}
    #hero {
      height: 100%;
      display: grid;
      place-items: center;
    }
    
    #hero-content {
      margin-top: calc(-1 * var(--header-height));
    }
    
    /*Ignore; for demonstrational purposes*/
    body {margin: 0}
    header {background-color: lightpink}
    main {background-color: lightblue}
    
    /*Center cross*/
    body::before, body::after {
      content: "";
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: black;
    }
    body::before {
      width: 2rem;
      height: 2px;
    }
    body::after {
      width: 2px;
      height: 2rem;
    }
    <body>
      <header></header>
      <main>
        <section id=hero>
          <span id=hero-content>Hero content</span>
        </section>
      </main>
    </body>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search