Document Flow
HTML Documents without any styling information applied via CSS have a "normal flow" or default parameters for how the browser displays them. By default, html elements will all flow to the left, and be displayed one after the other in the order they exist in the HTML. Embedded links (anchor or 'a' tags) will continue as normal text in this flow, wrapping lines and flowing left.
The HTML (and any associated CSS) are rendered by the browser through a sequence of steps:
- The browser loads the HTML from the network.
- The browser parses the HTML and creates the DOM (Document Object Model) as a representation of the page in computer memory.
- The browser fetches most linked assets (images, videos CSS, etc.). *Javascript is fetched later
- The browser parses any present CSS and sorts it by the various types of selectors (id's, classes, elements, etc.).
- The parsed CSS is linked to the appropriate nodes in the DOM by selector to create the render tree.
- The render tree is laid out in the order it should be displayed based on the applied styles.
- The browser renders the page out to the display.
Certain styling applied by CSS can remove elements from the "normal flow" causing the resulting appearance of the web page to be significantly different from the layout of elements in the HTML. This can provide tremendous flexibility in what a page looks like without significant changes to the order or structure of the HTML. For both versatility and ease in development and support as well as accessibility for screen readers and other assistive technologies, HTML should be structured to provide semantic clues, readable code, and concise and clear editing structure. CSS should be applied via linked stylesheets (avoid inline styling to keep code clean) to handle the visual layout of the resulting page separately from the writing of the content in the HTML.
CSS Overview
CSS Stands for Cascading Style Sheets. Following the HTML being read by the browser and parsed into the DOM (Document Object Model), the browser will parse the CSS. CSS can be provided inline, at the head of a document, or as a separate linked style sheet. The latter of these three is the most flexible and generally best practice for readability and editability. Inline styling should generally be avoided as it causes clutter and is more difficult to edit and keep organized then keeping all your style rules in one place.
The Cascading portion of the acronym refers to how the style rules are prioritized/rendered. There can be multiple layers of rule selection that apply to a singular element in the HTML document. If any two rules are in conflict as the browser cascades through the sheet, the last rule listed in the style sheet will take precedence over earlier rules. If multiple selectors apply to a singular element and none of the rules are in conflict, then all will be applied. If the browser encounters any style rules that are incompatible or unreadable, it will simply ignore them and move on through the document.
CSS uses a number of possible selectors to figure out what rules should be applied to which nodes in the DOM.
The selector is followed by {curly braces} Any applicable style rules between the curly braces will be applied
to all nodes in the DOM matching that selector. Nodes can be selected by:
- ID - Set in html with id="". Must be unique/specific to one element. ID selectors in CSS are prefaced with a # symbol, e.g. #elementid{}.
- Class - Set in html with class="". Usable across many elements that share that styling. Class selectors in CSS are prefaced with a period, e.g. .nav-link.
- HTML Element type - you can style all instances of a particular HTML Element type (< span >, < ul >, < img >, etc.) by using the type name as the selector in the CSS style sheet without any punctuation or special characters.
Selectors can be combined to increase specificity, or to apply the same rules across multiple selectors as
follows:
- selectors separated by comma,(e.g. a, img, .nav-link{}) will apply the style rules between the curly braces to all instances of each selector
- selectors separated only by spaces will add specificity (e.g. #main-doc img{}) will apply only to nodes that meet all the criteria - in this case any < img > elements within the element with id=main-doc
- selectors separated by a colon imply pseduo-classes or states of specific elements, e.g. button:active{} will apply style rules to buttons in their active or "clicked" state.
- 2 preceding colons, e.g. ::before or ::after or ::first-line, select pseudo elements - for instance - p::first-line would select the first line of each paragraph. For a list of common pseduo elements, click here.
Position Property
There are currently 7 possible settings for the position attribute of an element: static, fixed, absolute, relative, sticky, initial, and inherit.
- static (default)>
- fixed
- absolute
- relative
- sticky
- initial
- inherit
"static" is the default option for the position property. Items with static positioning are rendered "as-is" in the order of the document flow
"fixed" positioning will render the element relative to the viewport (browser window) and remove it from the document flow.
"absolute" positioning will render the element relative to its first positioned ancestor(e.g. not position:static;).
"relative" positioning will render the element relative to its normal position (e.g where it would appear with no specific position info).
"sticky" positioning is dependent on scroll position of the user's browser window. position:sticky will render the element as if it were position:relative until the element's scroll threshold is crossed at which point it will render the element as position:fixed.
The initial setting will set the property of that item to its default value (in the case of position, that will result in position:static)
The inherit settings will set the property of that item to the value of its parent element.
Display Property
There are many possible settings for the display attribute of an element: The major types are inline, block, inline-block, flex, grid, table and none. Initial and Inherit also work on display.
- inline (default)
- block
- inline-block
- flex
- grid
Inline is the default display type. It will render elements in the normal document flow, inline with the elements around them (no added line breaks). Height and width properties have no effect.
setting the display type to block will display the element as a block on a new line, taking the whole width.
inline-block displays the element as an inline level block container. The element itself is formatted as an inline element but will allow for height and width settings.
CSS Flexbox is a display type that allows for flexible and responsive alignment and sizing of elements within the flex container. The container is set to a display type of flex and then the arrangement of elements may be adjusted with various properties detailed in the section on CSS Flexbox here.
CSS Grid is a display type that creates a grid of rows and columns into which grid elements can be placed. Similar to flex, but in two dimensions simultaneously with some additional controls. Grid is detailed in its own section here.
Padding and Margins
Padding and Margins are similar CSS properties that affect the layout, primarily of block elements. Margin sizes affect the distance between containers and other elements on the page. Padding affect the distance between content and the border of its container. Margin will accept an :auto delcaration for centering purposes, but padding will not. Margins and padding can be differentiated for the four sides of the content in a single declaration in clockwise order - top, right, bottom, left. If only two values are declared, it will assume symmetry (left = right and top = bottom). Single sides may also be declared directly using padding-left or margin-left for instance.
Borders
Borders are drawn around the edge of a content area, outside the padding and inside the margins. Borders may have a variety of style, thickness, and color like many other HTML/CSS elements. Border properties include:- border-style (required)
- none - no border
- hidden - no visible border but affects table conflicts
- dotted
- dashed
- solid
- double
- groove
- ridge
- inset
- outset
- initial
- inherit
- border-width
- border-color
You must set a border style before you can set a width or color. Just like padding and margins, the 4 sides of a border can be set independently with different properties either through the use of multiple arguments or explicit selectors like border-top. Border width, style, and color can be set in a single declaration in that order (e.g. border: 5px solid red).
The property border-radius can be specified to round the corners of the border using the specified radial value.
Box Sizing
How the total size of an element is calculated depends on the box-sizing model in play. The default setting for this property is content-box which means the browser will apply any height or width specifications to the content only. Then padding, border, and margins will all be added to that content dimension externally. Alternately declaring box-sizing:border-boxwill include padding, border, and margins in the total size of an element which generally makes layout more consistent when aligning and sizing objects with a variety of padding, border, and margin configurations. The box-sizing:border-box; declaration is commonly made at the top of a stylesheet using the *, ::before, ::after selectors to apply the sizing model universally to all elements and pseudo elements.Flexbox
CSS Flexbox is a display type that allows for flexible and responsive alignment and sizing of elements within the flex container. The container is set to a display type of flex and then the arrangement of elements may be adjusted with the following properties:
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- center arranges elements evenly around the center of the flex container.
- flex-start arranges elements evenly starting at the beginning (left of flex container, unless reversed). This is the default value.
- flex-end works similar to flex-start but from the other end of the major axis.
- space-around arranges the items distributed with even gaps along the major axis including at the ends.
- space-between arranges the items distributed with even gaps along the major axis and half gap spaces at the ends.
- align-items
- stretch (default) - items are stretched to fill the height of the container.
- center - items are centered along the major axis of the container.
- flex-start - items are positioned at the start of the container.
- flex-end - items are positioned at the end of the container.
- baseline - items are aligned by the baseline of contents in the container.
- initial and inherit are options as well and function as usual.
- align-content
set to column or row (and -reverse) will arrange items within the flexbox vertically or horizontally. adding -reverse will render the elements bottom to top or right to left.
flex-wrap:wrap; will indicate that the content within the flexbox container should wrap as needed based on window size. The default is no wrap where elements will be resized/clipped when they start to overflow the container. Setting flexwrap: nowrap; will force items to not wrap and stay inline as the flexbox resizes (default).
flex-flow provides a shortcut to set both wrap and direction in a single declaration (i.e. flex-flow:row wrap;)
aligns items along the major axis of the flexbox (row or column as set by flex-direction).
similar to justify-content, but used to align items along the perpendicular or minor axis of the flexbox.
functions in similar fashion and with similar arguments to align-items (stretch (default), center, flex-start, flex-end, baseline, initial, and inherit). The difference is that align-content applies to the arrangement of lines of content within a flex-container that has multiple lines of content as opposed to the individual elements within a line of content.
Grid
To utilize the CSS grid layout attribute, after setting the display property of the container via display:grid; you can adjust spacing (gaps) of the rows and columns of grid items. All direct children of the container set to display:grid become grid items. The grid consists of rows and columns of elements, with row gaps between horizontal groups of content and column gaps between vertical groups of content. These can be set uniformly with grid-gap. A singular value will set all the columns and rows to that width. You can specify different widths for column gaps and row gaps either by providing two arguments for grid-gap where the first argument sets row-gap height and the second sets column-gap width, or by explicitly calling out the separate properties grid-row-gap and grid-column-gap.
For example:
display:grid;
grid-gap: 20px 10px;
is the same net result as:
display:grid;
grid-column-gap:20px;
grid-row-gap:10px;
Grid dimensions can be set using grid-template-columns and grid-template-rows. The arguments for
both of these properties specify the width of the column or row respectively (set all arguments to auto for
uniform widths). The number of arguments provided will determine the number of columns or rows in the grid
layout.
For example:
.grid-container{
display:grid;
grid-template-columns:50px auto auto auto;
grid-template-rows:25px 50px;
}
defines a grid with 4 columns and 2 rows. The first column will have a fixed width of 50px, and columns 2-4 will
have uniform width based on subdividing the remaining space in the container. The first row will have a fixed
height of 25px and row 2 will have a fixed height of 50px.
Grid Items
When placing grid items, use the lines between the rows and columns to specify the area of the grid that item is to occupy.
For example:
.item1{
grid-column-start: 1;
grid-column-end: 3;
}
will place an item that spans from the left edge of the grid to the line between column 3 and 4 of the grid.
Similarly:
.item2{
grid-row-start:2;
grid-row-end:4;
}
will place an item that spans from the gap between rows 1 & 2 of the grid to the gap between rows 4 & 5.
This can also be handled with a single declaration such as grid-column: 1/5; which would place an item between column gaps 1 and 5. You can also use the keyword span to specify a start and how many columns or rows an item will span. (e.g.grid-column: 1/span 3;)
It can be shortcut even firther using the grid-area command with the format grid-area: RowStart / ColumnStart / RowEnd / ColumnEnd or grid-area: RowStart / ColumnStart / Row Span / Column Span
grid-area and grid-template-area can also be used to name grid areas and map items onto them. When specifying grid-template-areas, each row in the grid is separated with matched apostrophes (') and each spaced argument within the apostrophes represents a column. You can us a period (.) to represent a grid space with no name.
For example:
.item1{
grid-area: myArea;
}
.grid-container{
grid-template-areas: 'myArea myArea myArea . .' 'myArea myArea myArea . .';
}
will specify a 5 column, 2 row grid (note the periods) where item1 will occupy the first 3 columns in both rows.