Proper adaptive alignment of the site header

Original author: Mary Lou
  • Transfer
  • Tutorial
Often seemingly simple typesetting tasks require a complex structure of HTML markup and the use of CSS tricks. Centering elements or aligning content can be very tedious. One of these tasks is to align the elements of the top of the site so that the logo is on the left and the menu items on the right. You can use float and position: absolute, and to align vertically - add margin and padding to different elements. It seems to be nothing complicated. But if the site should be displayed correctly on mobile devices, there are many problems.



The following describes a concise way to solve this problem.

HTML markup is as simple as possible:

Super Bad



The height of the header is fixed, add text-align: justify , for children:

header {
    text-align: justify;
    letter-spacing: 1px;
    height: 8em;
    padding: 2em 10%;
    background: #2c3e50;
    color: #fff;
}


Add display: inline-block for all nav elements so that you can arrange them one after another:

header h1,
header nav {
    display: inline-block;
}


In order for the text-align: justify attribute to work as we want, we need to use a little trick with psedo elements, which was found in the article Perfectly justified CSS grid technique using inline-block , by Jelmer de Maat:

header::after {
    content: '';
    display: inline-block;
    width: 100%;
}




The result was horizontal alignment, without using float and position: absolute . Now you need to align the elements vertically. When using vertical-align for nav elements, there will be a dependence on the height of the parent block - the header. And this is not very correct. Examples of using vertical-align: top and vertical-align: middle on jsbin. Below is probably the most convenient way to align vertically.

We use pseudo-elements again. using the example from the article Centering in the Unknown mentioned by Michał Czernow:

header h1 {
    height: 100%;
}
header h1::before {
    content: '';
    display: inline-block;
    vertical-align: middle;  
    height: 100%;
}

The result is what you need: It



remains to solve two problems: the correct display with a large amount of text in the header and adaptability. If the site title is too long, the layout will begin to move out: Use the trick with the pseudo-element on the header :




CSS code
header {
    text-align: justify;
    height: 15em;
    padding: 2em 5%;
    background: #2c3e50;
    color: #fff;
}
header::after {
    content: '';
    display: inline-block;
    width: 100%;
}
header > div,
header nav,
header div h1 {
    display: inline-block;
    vertical-align: middle;
}
header > div {
    width: 50%;
    height: 100%;
    text-align: left;
}
header > div::before {
    content: '';
    display: inline-block;  
    vertical-align: middle;
    height: 100%;
}



It looks much better:



Now let's move on to adaptability. There are several ways to solve this problem, you can simply not set the height of the header, and all internal elements will be adaptive to the height. You do not need a second trick with pseudo-elements, a live example on jsbin.
CSS code
header {
    text-align: justify;
    padding: 2em 5%;
    background: #2c3e50;
    color: #fff;
}
header::after {
    content: '';
    display: inline-block;
    width: 100%;
}
header h1,
header nav {
    display: inline-block;
    vertical-align: middle;
}
header h1 {
    width: 50%;
    text-align: left;
    padding-top: 0.5em;
}
header nav {
    padding-top: 1em;
}



If you need to set the height of the header, you will have to use the second trick with pseudo-elements, and add media query for screens of different sizes:

@media screen and (max-width: 820px){
    header {
        height: auto;
    }
    header > div,
    header > div h1,
    header nav {
        height: auto;
        width: auto;
        display: block;
        text-align: center;
    }
}


The result is adaptive and on mobile devices looks like this: In the example, 820px is used for clarity, on a live site, the value of course should be different, in accordance with the requirements. To support Internet Explorer 8, you must use “:” for pseudo-elements instead of “::”.





Final CSS
@import url(http://fonts.googleapis.com/css?family=Lato:400,700italic);
* { padding: 0; margin: 0; }
body { background: #1abc9c; font-family: 'Lato', sans-serif; text-transform: uppercase; letter-spacing: 1px;}
header {
    text-align: justify;
    height: 8em;
    padding: 2em 5%;
    background: #2c3e50;
    color: #fff;
}
header::after {
    content: '';
    display: inline-block;
    width: 100%;
}
header > div,
header > div::before,
header nav,
header > div h1 {
    display: inline-block;
    vertical-align: middle;
    text-align: left;
}
header > div {
    height: 100%;
}
header > div::before {
    content: '';
    height: 100%;
}
header > div h1 {
    font-size: 3em;
    font-style: italic;
}
header nav a {
    padding: 0 0.6em;
    white-space: nowrap;
}
header nav a:last-child {
    padding-right: 0;
}
@media screen and (max-width: 720px){
    header {
        height: auto;
    }
    header > div,
    header > div h1,
    header nav {
        height: auto;
        width: auto;
        display: block;
        text-align: center;
    }
}


Result:



Also popular now: