Full page site with vertical centering using css only

One of the big trends on the internet is the full page site. It consists of a single page site with multiple sections which you can scroll through. The trick of this is to have each section fill the screen and to centre the content inside.



The main features are:
- fixed header which stays at the top as we scroll
- sections with variable heights depending on the content height
- sections which fill the browser window
- sections which are constrained to match a certain aspect ratio e.g. a video player or image
- links in the navigation to jump to specific sections
- content can be centered within each section horizontally and vertically
- when we resize the browser it adapts and fills the window whatever the size
- crossbrowser support (IE8+, Firefox, Chrome, Safari)

So lets tackle each one step by step:

Fixed header
Let's create the navigation html inside header.

<div class="header">
    <ul>
        <li><a href="#auto">Auto</a></li>
        <li><a href="#fit">Fit</a></li>
        <li><a href="#wide">Wide</a></li>
    </ul>
</div>

We have given the header position fixed and a width to ensure it fills the screen. The z-index puts it in front of the other content on the page

.header {
    width: 100%;
    z-index: 2;
    position: fixed;
    background-color: #666;
}


Variable heights
We've added a container for the sections and some section html which will push the height larger

<div class="container box">
    <div class="section red">
        <p>Auto width and height</p>
    </div>
</div>

Here we have set the heights to 100% for the html, body and container. We have added padding to the container to prevent the header from overlapping the first content and for 100% height sections later.

html, body {
    margin: 0;
    height: 100%;
}

.container {
    padding-top: 38px;
    /* offset the height of the fixed nav to ensure height 100% is correct */
    height: 100%;
}

.box {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.section img {
    max-width: 100%;
}

.section p {
    margin: 0;
}


Fill the browser
Inside the container we can now add a section with a class called fit

    <div class="section fit green">
        <p>Fit width and height</p>
    </div>

And the css which goes with it tells it to fill the height on the container (the container has padding at the top to make 100% the height without the fixed nav)

.section {
    position: relative;
    width: 100%;
}

.fit {
    height: 100%;
}


Constrained to an aspect ratio
Inside the container we can add more section html.

    <div class="section wide yellow">
        <div class="content">
            <p>Constrained width and height</p>
        </div>
    </div>

The wide class uses a css trick where padding is a percentage of the width of the element. So if you want 16:9 aspect ratio you calculate 9 divided by 16 and then multiplied by 100. The content inside needs position absolute to line it up afterwards.

.wide {
    height: auto;
    padding-top: 56.25%; /* 9 / 16 = 0.5625 */
}

.wide .content {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
}


Links to jump to each section
Ensure hash urls are added to your links in the navigation.

<div class="header">
    <ul>
        <li><a href="#auto">Auto</a></li>
        <li><a href="#fit">Fit</a></li>
        <li><a href="#wide">Wide</a></li>
    </ul>
</div>
<div class="container box">
   
    <div class="anchor" id="auto"></div>
    <div class="section red">
        <p>Auto width and height</p>
    </div>

    <div class="anchor" id="fit"></div>
    <div class="section fit red">
        <p>Fit width and height</p>
    </div>

    <div class="anchor" id="wide"></div>
    <div class="section wide red">
        <div class="content">
            <p>Constrained width and height</p>
        </div>
    </div>

</div>

To ensure the header does not overlap our content we will add some css to tell the browser the top of the content is lower down. This also lines up each anchor id when you jump between sections.

.anchor {
    padding-top: 38px;
    margin-top: -38px;
}


Centered content horizontally and vertically
For this we can utilise tables and table cells to centre the content. It requires two extra containers unfortunately but as pure css it stays very efficient for the browser compared to js techniques.

    <div class="section fit yellow">
        <div class="t">
            <div class="tc">
                <h1>Centered content</h1>
                <p>works here</p>
            </div>
        </div>
    </div>

The table css sets it to 100% width and height to fill the div it's inside. The cell inside has vertical align middle and text align center to complete the functionality.

.t {
    display: table;
    width: 100%;
    height: 100%;
}

.tc {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}


Hope this helps you set up a full page site using css only. It also works in IE8+, Firefox, Safari and Chrome which means you can support those older browsers too.

Here is working version you can play with: