You’ve learned how to use CSS to change the appearance of text and manipulate colors. Those are likely the most common actions you’ll take with CSS, but it is much more powerful than that.
You can place elements wherever you want on a page without changing the underlying CSS. In Chapter 6 you learned about using HTML to structure a page. Now it’s time to learn how CSS can change the layout.
In Chapter 6, you were briefly introduced to the box model. The simplest way to put it is that CSS treats every HTML element as if it’s in its own box. By default, when a browser renders a webpage, the boxes flow onto the page in sequence as it encounters them in the code. This is sometimes called normal flow.
FIGURE 15.1 shows an example from the New York Times.
For each element, you can control a number of parameters:
The width and height of its box
Border color and thickness around the box
Whether or not the border is visible
Whether the box itself is visible
Where the box fits in the flow of elements on the page
How much space is around the box (margins), and around the content within the box (padding)
You can also change the position of an element in the flow of a page by choosing whether to make it an inline element or a block element. This can have an effect on how much space is (or can be defined) around the box.
Using the display
property, you can change the flow of an element. These are the most common values:
block
makes an element start on a new line and take up the full width of the container (forming a block of content, if you will).
inline
leaves an element in its position in the flow of content. It will not start on a new line, and it will take up only the horizontal space it needs. Certain properties, like height
and width
, have no effect on inline elements.
inline-block
is a hybrid of inline
and block
. The element will display inline but take on the properties of a block, like height, width, and spacing.
none
completely hides the element and removes it from the flow. It will only be viewable in source code.
To set a link to display as a block-level element:
In your style sheet, type the selector you want to change. In this example, use a
.
If you want the style to apply to a specific class, type a period followed immediately by the class name, then add a left curly brace. Here, use .button {
.
Type the property you want to assign to the selector. In this case, use display: block;
.
Type }
to close the style declaration.
This moves any link (<a>
tag) of the class button
from inline to its own block (FIGURE 15.2).
Unless you specifically define a height and width, they’ll default to a size big enough to hold the content (with the caveat that block-level elements are the full width of their parent container). To define a specific size, you can use the height
and width
properties. They accept the same units you would use to measure text size: px
, em
, rem
, and %
.
To set a specific height and width for an element:
In your style sheet, define the element to which you want to apply the rule, followed by a left brace. In this example, use aside {
.
Type width:
followed by the desired width. In this case, 400px;
.
Type height:
followed by the desired height. In this case, 200px;
.
Type }
to end the style declaration.
This gives you a 400x200 box for all aside
elements (FIGURE 15.3).
Finally, you can set minimum and maximum values for both height and width.
The minimum properties are min-width
and min-height
. They say, “Do not drop the container’s size below this value.” If you set min-width: 300px;
the container will always be at least 300px wide but can be wider, depending on the content.
And max-width
and max-height
say, “Do not let a container go beyond this size.” So max-height: 500px
means the container can be shorter than, but will never be taller than, 500px.
Each of these can make sense depending on the context. But the main thing to remember is that the height
and width
properties are fixed. They will always be exactly the size you define, no matter the size of the browser window or parent container (FIGURE 15.4).
In Chapter 14, you learned how to adjust spacing for text to make it more readable and how to add whitespace when necessary. You can do the same thing with entire elements and everything they contain—text, images, and otherwise.
As stated earlier, there are two ways to add spacing to an element: around the outside of the whole box, which is margin
, and around the content inside the box, which is padding
. That, taken with height
, width
, and border
, creates the complete amount of space a block-level element takes up (FIGURE 15.5).
You can define padding
and margin
values using the same units as those for height
and width
. Using a single value for either property applies the same value to all four sides of the element.
To add padding and margin to a paragraph:
In your style sheet, type the selector you wish to target, followed by a left curly brace. In this case, use p {
.
Type padding:
followed by the value; this example uses 20px;
.
Type margin:
and the value; here, use 20px;
.
Type }
to close the declaration.
This adds a little extra spacing to your paragraphs (FIGURE 15.6).
With both padding
and margin
, you’re not locked into assigning a single value to the attribute for the entire element. You can define a different value for the left, top, right, and bottom of each box. There are a few ways to do it.
You can explicitly define each side, as shown in TABLE 15.1.
Table 15.1 Padding and Margin Side Properties
Padding |
Margin |
---|---|
|
|
|
|
|
|
|
|
You can also use a shorthand version, in which you set the values for each of the four sides individually in a single declaration:
padding: [top] [right] [bottom] [left]; margin: [top] [right] [bottom] [left];
For each property the values are applied in clockwise order around the element, starting from the top. Slightly shorter would be:
padding: [top/bottom] [left/right]; margin: [top/bottom] [left/right];
Here, you have two values instead of four, where the first value sets the top and bottom spacing, and the second value sets the left and right spacing.
Finally, there’s also a three-value declaration:
padding: [top left/right bottom]; margin: [top left/right bottom];
Here, the first value is for the top spacing, the middle value is for the left and right, and the last is for the bottom.
margin: auto
Sometimes when you set a width, you might want to center the container on the page. That’s very easy to do using the margin
property. You can set margin
to the value auto
, and it will calculate the width of the parent container, subtract the width of your target element, and distribute the leftover value evenly on both sides.
Say you have a wrapper
class that has a width
of 800px
:
.wrapper { width: 800px; }
On most tablets and desktop devices, the width of the window (and therefore, the entire website) will be more than 800px, and your content will look like what you see in FIGURE 15.7, where there is a lot of space to the right of the container.
Using the keyword auto
with margin
allows you to automatically center that content in the middle of the window.
You can use the auto
keyword in two ways: as the only value for margin
(margin: auto
) or in conjunction with a set top and bottom (margin: 30px auto
). Both cases result in horizontal centering. The latter also includes a 30px margin before and after the container.
To center an element automatically with margin: auto
:
In your style sheet, type the selector you wish to target, followed by a left curly brace. In this case, use .wrapper {
.
On a new line, type width:
, followed by the value. In this case, 800px;
.
Setting a width for the container isn’t strictly necessary, but without it you will not see the results of using the auto
keyword.
On a new line, type margin:
, then the values, including values for options like top or bottom margins. In this case, type 30px auto;
.
On a new line, type }
.
Your full ruleset looks like this:
.wrapper { width: 800px; margin: 30px auto; }
That results in a div
with the class wrapper
being center aligned on a page (FIGURE 15.8).
By default, elements flow onto the page in the order they appear in the HTML, depending on whether they are a block or inline element. FIGURE 15.9 shows how the elements on a page naturally flow, with block-level elements outlined. You can see that block-level elements take up the entire width of the page and dictate most of the natural flow. Links and other text formatting fall in line with those blocks (like the links in the unordered list).
However, there are a few ways to change the flow of elements. You might want to do this to pull out certain content (like a quote or an aside), draw attention to an image, or even reorder elements when viewing the site on a smaller device.
The most common way to change the flow of HTML elements is to use the float
property.
The float
property takes an element out of its normal flow and places it to the right or left inside the container:
aside { float: right; }
This moves the aside
element to the right and lets everything else flow around it (FIGURE 15.10). You can see the code in CODE 15.1.
Note that the floated element will be surrounded by any elements below it, so if you want it to appear in the top of a container, it will have to be the first element.
You can even use float
to create a grid of elements. Floating all elements of a particular type takes them out of the normal flow and lines them up next to each other. Before the creation of the layout modules Flexbox and CSS Grid (which you’ll learn about in Chapter 16), this is how many web designers created column-based layouts.
To create a grid layout with floats:
In your style sheet, type the selector you wish to target, followed by a left curly brace. This example targets paragraphs, so use p {
.
Type float:
.
Type left;
to force the element to float on the left side of its container.
To force the element to float on the right side, you would use the value right
.
Type margin:
to set the spacing between the elements. For this example, use 15px;
.
Type width:
to set the width of each element. This example uses 300px;
.
Type }
to close the style declaration.
This makes the paragraphs flow onto the page in a grid (FIGURE 15.11).
While this can work, it can also cause havoc for any elements in the normal flow. Elements can end up in unexpected places to work their way around floated elements. And although there are better ways to achieve a grid (as you’ll see in Chapter 16), you could always use the clear
property, which tells the element to place itself below any floated content:
.next-section { clear: left; }
Other values for this property include right
and both
.
Another way to place elements and containers precisely is by using the position
property. It accepts several values, which I’ll list in a moment.
This property is often accompanied by a set of properties that position elements in specific areas of the window or container: left
, right
, top
, and bottom
. These all accept the normal units (px
, em
, rem
, %
), and they all have slightly different meanings depending on the value of position
. Here are the values for position
, and positioning properties:
static
: This is the default value. There is no special positioning.
relative
: Places the container based on its normal position. The directional properties will move the container away from its normal position.
So left: 50px
moves the container to the right by 50 pixels, similar to margin
.
fixed
: The container is in a fixed position on the page, so no matter what part of the page is being displayed to the user, the container will be in the same spot.
The directional properties in this instance are exact coordinates; left: 0; top: 0;
means the container will be at the left edge at the very top of the window.
absolute
: The container is positioned in a fixed position in its parent container.
Directional properties work the same way as those for the fixed
position.
sticky
: The container is positioned relatively (as in the normal flow) until the user reaches a specific scroll position. Then it sticks in place on the screen.
For example, top: 0
positions the element relatively in the normal flow until the page is scrolled and there are zero pixels between the element’s top edge and the visible area of the webpage. Beyond that threshold, the element behaves as if it used fixed positioning and will be fixed to zero pixels from the top.
To get a better idea of how each of these work, check out Video 15.5.
To make a sticky sidebar:
The starting markup for this task is listed below. Since there’s no HTML5 element specifically for “wrapping” other elements (from a semantic meaning standpoint), it’s common practice to use the <div>
element with a wrapper
class:
<div class="wrapper"> <aside> ... </aside> <main> ... </main> </div>
In your style sheet, type .wrapper {
.
Type width: 800px;
.
Type margin: 30px auto;
.
Type }
.
Type main {
.
Type width: 500px;
.
Type }
.
Type aside {
.
Type width: 260px;
.
Type padding: 15px;
.
Type float: right;
.
Type position: sticky;
.
Type top: 0;
.
Type }
.
This code produces a two-column layout with a sticky sidebar. You can also add a background and border to aside
to distinguish it a bit (FIGURE 15.12). You can see the code in CODE 15.2 and 15.3.
Although taking elements out of the natural flow can create interesting layouts for your content, you can run into situations where content overlaps and becomes unreadable. For example, if you had not set the width
property on the main div
in the previous task, your users would have run into a problem (FIGURE 15.13). Because we’ve fixed the position of the aside, the browser is essentially saying, “Keep the aside in this spot, no matter what the rest of the flow looks like.” That means when the user scrolls, the main text overlaps the aside.
CSS has a fix for that: the z-index
property. You can think of z-index
as a layer or stacking property, where the value is an integer. The closer the integer is to 0, the “lower” on the page the element is (FIGURE 15.14). You can also think of elements with a lower z-index
as being “behind” elements with a higher z-index
.
A ruleset that uses z-index
looks something like this:
aside { position: fixed; top: 0; z-index: 10; }
z-index
One practical example of using z-index
is to create a piece of content that should be shown in front of the rest of the content. You see this with popups asking you to join mailing lists, for example.
In this task, you will learn the basics of how to do that. In the real world, you might make the overlay dismissible with a bit of JavaScript, but you will clearly see how z-index
works.
To create an overlay using z-index
:
The markup being styled will be the following:
<div class="overlay">
<h3>This is an important alert!
→</h3>
</div>
<header>
<h1>A Case of Identity</h1>
</header>
<main>
(content goes here)
</main>
In your stylesheet, first type the element you want to apply the styles to, followed by a left curly brace. In this case, .overlay {
.
Now set the position of the element to absolute by typing, on a new line, position: absolute;
.
Since the element is absolute, you can now use positional properties to move it. Move it down the page a little bit. On a new line, type top: 10%
;.
Move the element in front of all other elements using z-index
. Since the default z-inde
x is 0, on a new line type z-index: 1000
;.
This will make sure the overlay is above the rest of the content—as long as nothing has a z-index
over 1000.
Strictly so you can more easily see the result, apply a background color to the element. On a new line, type background: #cfcfcf
;.
You can also center the text. On a new line type text-align: center;
.
Finally, adding some padding so it stands out a bit more. On a new line, type padding: 40px;
.
On a new line, type }
.
This results in a block of text that is layered on top of the main page (FIGURE 15.15).
In recent years, great strides have been made in creating layouts with CSS. The practice of laying out elements on a webpage moved from tables, in HTML, to floating elements and clearing them using CSS. There are many frameworks designed to help you to create beautiful grid layouts. A framework is a set of structured files (HTML, CSS, and maybe JavaScript) that give you a head start on creating websites. See the sidebar “Using CSS Frameworks” to learn more.
But now, CSS Grid and Flexbox (two suites of layout properties you’ll see in Chapter 16) have much wider browser support, so they should be used instead of floating and clearing elements. They allow for code that is semantic, much cleaner, and easier to support. The techniques you saw in this chapter—floats, positioning, and changing the default flow—still have their place in web design, though.
At this point, you have enough tools in your toolbox to create nice-looking layouts. In Video 15.6, you put most of that to the test by creating a pricing table.
You know all about how to change the default flow of a page and the elements/containers on it. You’ve learned about common methods like floating (and clearing those floats), changing the position of elements, and z-index
.
You can probably imagine that you’ll run into a lot of fringe cases when you try to make these properties work for complex layouts—which is why frameworks became popular in the first place. But CSS has solved that with two important new systems: CSS Grid and Flexbox.