Boxes
As Rachel Andrew has reminded us, everything in web design is a box, or the absence of a box. Not everything necessarily looks like a box—border-radius
, clip-path
, and transforms
can be deceptive, but everything takes up a box-like space. Layout is inevitably, therefore, the arrangement of boxes.
Before one can embark on combining boxes to make composite layouts, it is important to be familiar with how boxes themselves are designed to behave as standard.
The box model
The box model is the formula upon which layout boxes are based, and comprises content, padding, border, and margin. CSS lets us alter these values to change the overall size and shape of elements’ display.
Web browsers helpfully apply default CSS styles to some elements, meaning they are laid out in a reasonably readable fashion: even where author CSS has not been applied.
In Chrome, the default user agent styles for paragraphs (<p>
) look like…
p {
display: block;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
… and unordered list (<ul>
) styles look like…
ul {
display: block;
list-style-type: disc;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 40px;
}
The display
property
In both the above examples, the element's display
property is set to block
. Block elements assume all of the available space in one dimension. Typically, this is the horizontal dimension, because the writing-mode
is set to horizontal-tb
(horizontal; with a top to bottom flow direction). In some cases, and for some languages (like Mongolian), vertical-lr
is the appropriate writing mode.
Inline elements (with the display
value inline
) behave differently. They are laid out in line with the current context, writing mode, and direction. They are only as wide as their content, and are placed adjacently wherever there is space to do so. Block elements follow flow direction, and inline elements follow writing direction.
Thinking typographically, it could be said that block elements are like paragraphs, and inline elements are like words.
Block elements (also called block-level elements) afford you control over both the horizontal and vertical dimensions of the box. That is, you can apply width, height, margin, and padding to a block element and it will take effect. On the other hand, inline elements are sized intrinsically (prescribed width
and height
values do not take effect) and only horizontal margin and padding values are permitted. Inline elements are designed to conform to the flow of horizontal placement among other inline elements.
A relatively new display property, inline-block
, is a hybrid of block
and inline
. You can set vertical properties on inline-block
elements, although this is not always desirable—as the proceeding illustration demonstrates.
Of the basic display
types, only none
remains. This value removes the element from the layout entirely. It has no visual presence, and no impact on the layout of surrounding elements. It is as if the element itself has been removed from the HTML. Accordingly, browsers do not communicate the presence or content of display: none
elements to assistive technologies like screen reader software.
Logical properties
What are logical properties and does their existence imply the existence of illogical properties? English speakers accustomed to reading left to right (direction: ltr
) and top to bottom (writing-mode: horizontal-tb
) find it logical to use properties that include the words “left”, “right”, “top”, and “bottom” when applying styles like margin and padding.
.icon {
margin-right: 0.5em;
}
It’s when the direction or writing mode changes that this becomes illogical, because left and right (and/or top and bottom) are flipped. Now the margin you put on the right you really need on the left.
Logical properties eschew terminology like “left” and “right” because we know they can be reversed, making the terms a nonsense. Instead, we apply styles like margin, padding, and border according to the block and inline direction.
.icon {
margin-inline-end: 0.5em;
}
In a ltr
direction, margin-inline-end
applies margin to the right. In a rtl
direction, margin-inline-end
applies margin to the left. In both cases, it is applied where it is needed: at the end of the inline dimension.
Formatting contexts
When you apply display: flex
or display: grid
to a <div>
, it continues to behave like a block element, using display: block
. However, it changes the way its child elements behave. For example, with just display: flex
(and no other Flexbox-related properties) applied to the parent, its children will distribute themselves horizontally. Or, to put it another way, the flow direction is switched from vertical to horizontal.
Formatting contexts are the basis of many of the layouts documented in this project. They turn elements into layout components. In Composition, we'll explore how different formatting contexts can be nested, to create composite layouts.
Content in boxes
The web is a conduit for primarily textual information supplemented by media such as images and videos, often referred to collectively as content. Browsers incorporate line wrapping and scrolling algorithms to make sure content is transmitted to the user in its entirety, irrespective of their screen sizes and dimensions, and settings such as zoom level. The web is responsive largely by default.
Without intervention, it is the contents of an element that determines its size and shape. Content makes inline
elements grow horizontally, and block
elements grow vertically. Left to its own devices, the area of a box is determined by the area of the content it contains. Because web content is dynamic (subject to change), static representations of web layouts are extremely misleading. Working directly with CSS and its flexibility from the outset, as we are here, is highly recommended.
The box-sizing
property
By default, the dimensions of a box are the dimensions of the box’s content plus its padding and border values (implicitly: box-sizing: content-box
). That is, if you set an element to be 10rem
wide, then add padding on both sides of 1rem
, it will be 12rem
wide: 10rem
plus 1rem
of left padding and 1rem
of right padding. If you opt for box-sizing: border-box
, the content area is reduced to accommodate the padding and the total width equals the prescribed width
of 10rem
.
Generally, it is considered preferable to use the border-box
model for all boxes. It makes calculating/anticipating box dimensions easier.
Any styles, like box-sizing: border-box
, that are applicable to all elements are best applied using the *
(“universal” or “wildcard”) selector. As covered in detail in Global and local styling, being able to affect the layout of multiple elements (in this case, all elements) simultaneously is how CSS brings efficiency to layout design.
* {
box-sizing: border-box;
}
Exceptions
There are exceptions to the border-box
rule-of-thumb, such as in the Center layout where measurement of the content is critical. CSS's cascade is designed to accommodate exceptions to general rules.
* {
box-sizing: border-box;
}
center-l {
box-sizing: content-box;
}
Only where the height or width of a box is constrained does the difference between content-box
and border-box
come into play. For illustration, consider a block element placed inside another block element. Using the content-box
model and a padding of 1rem
, the child element will overflow by 2rem
when inline-size: 100%
(equivalent to width: 100%
in a horizontal-tb
writing mode) is applied.
Why? Because inline-size: 100%
means “make the width of this element the same as the parent element”. Since we are using the content-box
model, the content is made 100%
wide, then the padding is added on to this value.
But if we use inline-size: auto
(we can just remove inline-size: 100%
, since auto
is the default value) the child box fits within the parent box perfectly. And that’s regardless of the box-sizing
value.
Implicitly, the height
is also set to auto
, meaning it is derived from the content. Again, box-sizing
has no effect.
The lesson here is the dimensions of our elements should be largely derived from their inner content and outer context. When we try to prescribe dimensions, things tend to go amiss. All we should be doing as visual designers is making suggestions as to how the layout should take shape. We might, for instance, apply a min-height
(as in the Cover layout) or proffer a flex-basis
(as in the Sidebar).
The CSS of suggestion is at the heart of algorithmic layout design. Instead of telling browsers what to do, we allow browsers to make their own calculations, and draw their own conclusions, to best suit the user, their screen, and device. Nobody should experience obscured content under any circumstances.