0

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?

Page COW
  • 515
  • 13
  • 31

3 Answers3

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>
Brett Donald
  • 6,745
  • 4
  • 23
  • 51
  • It's not really clear what you mean by "centered" in your original question. "Centered" with respect to what? The screen? The container? Vertically or horizontally? EDIT: OP deleted his comment – Jake Mar 09 '23 at 23:31
  • @Jake The OP mentions "I just want to center one sentence on the screen". – Oskar Grosser Mar 09 '23 at 23:32
  • Yeah I know, and I think his gripe with your solution is that the "Content" string is not vertically centered with respect to the screen, but only within the `
    ` element. So at the end of the day, it's like 60% of the way down the screen or something. I'm just trying to get him to clarify what he wants though, your solution is very clean if that is his end goal.
    – Jake Mar 09 '23 at 23:34
1

@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>
Jake
  • 862
  • 6
  • 10
1

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 (static) 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>
Oskar Grosser
  • 2,804
  • 1
  • 7
  • 18