Chapter 4, Flexbox and Float
This reading summarizes and expands on the concepts of responsive and flexible layouts that we learned in chapter 4.
If you don't have Chapter 3, here's a link to a copy of a scan of the chapter. To respect the author's copyright, the link is only valid on-campus or with a password. Ask Scott if you don't have that password.
Mobile First¶
We should first design our websites so that they work effectively on small devices, and only later take advantage of greater space. Some rules of thumb:
- don't lay things out horizontally; stack things vertically
- give images CSS declarations like
width:100%
so that they scale to smaller displays - don't use table elements and such that might be wider than the display
- specify widths in percentages when feasible
- don't specify widths of elements in pixels (or, at least, wide widths) which might result in the dreaded horizontal scrolling
inline-blocks¶
In the last chapter, we learned about inline elements, like span
, that
are found in running text and would move around as the browser gets wider
and narrower.
We also learned about block elements, which use the box model, can (typically) contain other block elements, and stack vertically on the page.
We now know about inline block elements, achieved with
display:inline-block
. Such elements act like inline elements in terms of
filling out the width of their container (moving other inline elements up
from the next line until there's no more space), but they act like block
elements in that they can contain other block elements.
Note that the default width of a block or inline-block element is 100%
,
which means that there is never any room left to bring another one up from
the next line. So, it only makes sense to use inline-block where you are
setting the width (or it's a replaced element, like an img
, and so the
width is derived from the contents). Like this:
selector {
display: inline-block;
width: 20%; /* five on a line */
...
}
New HTML¶
- main The main content of a page. Bigger than an article
- div A meaningless block container. Useful for structuring the page
Flexbox¶
With Flexbox, there is
- a container that is limited in size. Presumably takes the whole screen or a portion thereof. Get these with
display:flex
. Contrast that with a Wikipedia page that is as long as it needs to be - a set of flex-items to be displayed, all children of the container. This is automatic.
- a direction or main axis that the children will be oriented in (horizontally or vertically)
- a cross axis that is perpendicular to the main axis
- a specification for what happens with any leftover space in the flex container
Flex containers can be nested, so you have have rows with columns, columns within rows, even rows within rows and columns within columns.
Flex items can grow and shrink. We learned two uses of the flex
shorthand property:
flex: 0 1 auto
means don't grow me, shrink me if needed, and calculate my size from my contentsflex: 1 1 auto
means grow me as much as possible, shrink me if needed, and calculate my size from my contents
Flexbox Simplified¶
I really like our book's example of flexbox in Ottergram, because it shows how sophisticated and powerful it can be. But it's a tough place to start. I strongly urge you to start with a simple case. The simple cases have at least the following features:
- a parent element and two or more children
- the parent will set the following:
display:flex
which is what makes it a flex parentflex-direction
which determines whether the children are in a row or a column
- each child (flex-item) can (optionally) set
flex: grow shrink basis
So, at minimum, you need two CSS properties on the flex parent to
use the flexbox feature. (Actually, there's probably a default for
flex-direction
, but let's not.)
Take a few minutes to look at these flex examples
New CSS Properties¶
Pretty much all of these are related to the new flexbox layout
- display:flex to specify that an element is a flex container/parent.
- flex-direction row or column
- flex how a flex item (child) shrinks or grows
- align-items aligning (e.g. centering or stretching) flex-items. If the item doesn't fill the space allocated to it, where does it end up in that space. See more at MDN align-items
- justify-content what happens with leftover space in a flex container?
- overflow set what happens when an element's contents is bigger than it is. Scroll? Hide? Show?
- order what order does this flexitem go in? source order? after others? before others? contents is bigger than it is. Scroll? Hide? Show?
- text-shadow can add a shadow to some text by reprinting the text in a different color and a small displacement
- white-space what happens with white space in an element: normal? nowrap?
Absolute and Relative Positioning¶
Normally, we let the browser figure out where an element should land on the page, based on its size, the size of the container, whether it's a block or inline element, and so forth. This is because the default value of the position
CSS property is static
. It has two other interesting values:
position:relative
which allows you to shift the element from its static positionposition:absolute
which allows you to place the element within a Cartesian coordinate system
Here's a sentence in which a single red word has been moved from its usual place. Of course, we could use that class again, to raise another word out of its place.
Here's how that's done. First, the CSS:
.up_and_right {
position: relative;
top: -1em;
left: 2em;
color:red;
}
Here's the HTML:
<p>Here's a sentence in which a single red <span
class="up_and_right">word</span> has been moved from its usual
place. Of course, we could use that class again, to raise another word
out of <span class="up_and_right">its</span> place. </p>
In general:
- The element is shifted vertically using either
top
orbottom
and giving a signed distance by which to move the top or bottom of the element. - It's shifted horizontally using either
left
orright
and another signed distance. - The starting location is where it would have been if it had been
position:static
(the default) rather thanposition:relative
. - Note that other elements don't move as a result of the movement of this one. (There's a gap left in the sentence above, where the word was moved from.) The moved element can even overlap other elements; that can't happen with float.
You might wonder why subtracting 1em from the top
causes the word
to move up. That's because the coordinate system for absolute and
relative is a little different from the x,y Cartesian coordinate
systems you learned in middle school or high school:
- left increases as you go left-to-right, just like x does,
- top increases as you go down, unlike y which decreases as you go down.
The reason for this weird coordinate system is that the beginning of the document is the main origin, and the beginning of the document is at the top of the page.
Position absolute is similar to position relative, except that the distances are measured not from the element's static position but in an absolute coordinate system, where the origin of the system is the first non-static ancestor and if no non-static ancestor is found, the browser window.
That last sentence is a little weird, so let's rephrase it to give us
another chance to understand it. Suppose the element that we want to
place is D (for "descendant"). Consider the whole chain of ancestors
that D has, all the way up to the body. If any of those ancestors,
call it A, has position:relative
(or anything other than the default
which is position:static
) then D is placed relative to A. That is, A
sets the coordinate system. If there is no such ancestor, then D is
placed with respect to the browser window.
Positioning on a Grid¶
Therefore, another use of position:relative
is to set the
coordinate system for its descendants. I like to think of this as "my
descendants are positioned relative to me". Here's an example. Each
of the colored boxes is 100x100 px. The outer green box is 600px wide
by 200px high.
This is done by:
- putting
position:relative
on the ancestor (here the box with gray background) - putting
position:absolute; top:100px; left:50px
on the pink child - putting
position:absolute; top:0px; left:-50px
on the green child - putting
position:absolute; bottom:50px; right:100px
on the purplish child
Use this feature sparingly. Sites where everything is positioned in
absolute coordinates are incredibly inflexible. You want a site that is
responsive to the size of the browser. Nevertheless, sometimes
position:absolute
can be useful.
Note that with position:static
, elements can never overlap. In
particular, text can't overlap. But with position:absolute
and
position:relative
you can do that, if you want.
Positioning Checklist¶
It's easy to get confused about the CSS properties you need to use absolute positioning. Here is a checklist:
- put
position:relative
on the desired ancestor - put
position:absolute
on the element you want to position - set two coordinates on the element you want to position.
The coordinates are usually top
and left
but they don't have to
be. You need to have:
- exactly one horizontal coordinate, either
left
orright
- exactly one vertical coordinate, either
top
orbottom
Flexbox versus Float¶
Flexbox is relatively new (circa 2014, though proposals go all the way back to 2009). Prior to widespread support for flexbox, web developers used float, which still has some useful features and is still worth knowing about.
Here's a simple example of float, where we get the text to wrap around an image:
Hermione Granger was indispensable in the Harry Potter series. Harry had the title role, and he was clearly critical to the story, but he did not have exceptional magical skill. His nemesis, Lord Voldemort, was an extraordinary wizard, matched only by Dumbledore. Harry, was good, but no more than good. Hermione, on the other hand, was "the brightest witch of her age" according to Remus Lupin. There was no spell she couldn't do, and her cleverness and foresight saved Harry countless times.
Float causes the floated elements to be
- Removed from the flow, so that later stuff moves up on the page, and
- shoved back into the page, causing block elements to overlap it and inline elements to wrap around it.
The example above shows the idea. Hermione's picture is floated (to the left in this case) and the paragraph text (inline elements) flows around it.
Centering Block Elements and Text¶
People love centering, particularly novice designers. Centering moves things away from the edges, which makes it feel more comfortable, without having to decide how much to move it. But there are two kinds of centering. There's centering block elements and centering inline elements like text. Let's start with centering text:
Centering Text¶
Centering text is pretty easy: just specify text-align:center
on its
parent element (or, in general, some ancestor, since the setting is
inherited.)
You should almost never center lines of text in a paragraph. You get ragged edges left and right, which looks ugly. Also, depending on the font, amount of text and the width of the region, the last line may be weirdly short (and centered). Here's a Tolkien quote:
You probably don't want that single word centered on the second line. But that can happen (and all-too-often does) when you center text and don't have complete control over browser-width, font-size, and the like.
Instead, what you probably want is to have normal, left-aligned text in a box that is itself centered. Let's see how to center boxes.
Centering Blocks¶
Here's an example of a block element (blue background) centered within its container (red border):
Note that, by default, block elements are width:100%
which means that
they are as wide as their container will let them be. So, by default,
centering is not possible, because there's no extra space to center
within. Therefore, to center a block element, you usually have to set its
width to something smaller than its normal width. The blue block above is
80% of its container. One exception is IMG elements, since they get their
width from the actual image, not from the container. However, pictures
are often quite wide, so you typically have to scale them down using a
width
setting anyhow.
The trick to centering a block element is to set its margin-left
and
margin-right
to auto
. Auto margins means to take whatever space is
leftover in the container and distribute it equally to the two margins.
The example above used a shorthand: margin:10px auto
which means the top
and bottom margins are 10px and the left and right are auto
.
Galleries with Floating Elements¶
We often want galleries of elements, where there should be as many on a
line as will fit, but fewer if necessary, without any horizontal
scrolling. One way to do that is by setting display:inline-block
and
set the width on the gallery elements, which allows you to put arbitrary
content in each element, while still having them fill the line like inline
elements.
Another way is to use float:left
as shown by W3schools
Gallery