software development blog
April 15, 2022

modern css concepts

This stuff changes everything. CSS used to be a nightmare for getting pages to do exactly what you want. We now have the convergence of ultra advanced browsers adhering to ultra advanced css standards. Don't get me wrong, css still takes a lot of messing around, but the results can now be spectacular.

css reset

This isn't exactly a modern concept, but it's still very relevant. All browsers give a starting set of css attributes to all of the html tags they can render. This is just to provide a simple fallback set of rules so that simple pages without a lot of css will look halfway decent. However, if you are creating a major web project, it's very important that you control the base set of rules for your pages. Every page in your project should start by linking in a reset.css file that you create to reset all of the tags you intend to use to a basic starting point. Look up css reset and you'll find many examples and schools of thought on the matter.

border-box

We can now specify that widths and heights of elements should be considered to include the border and padding thicknesses! (width:100%; now actually means 100%!) Simply set border-box box sizing for all elements by adding this to your reset.css:

* {
  box-sizing: border-box;
}

display: flex

The modern flex display offers everything you need to create pages that resize, realign and re-center, both vertically and horizontally in response to different screen sizes and orientations. The flex system is made up of a container element, and one or more child elements. Note that it is 'display: flex', not 'display: flexbox' as flexbox is a deprecated term.

Flex containers can be set up with a "row" based main axis, or a "column" based main axis. When you pick an axis to be the main axis, the other axis is known as the "cross" axis. This can be a little confusing because regardless of which you choose for the main axis, the flex container can apply various positioning and sizing to both axes, but each in different ways that may not always be perfectly obvious. Also, it's unclear which css rules are aimed at the main axis versus the cross axis -- i.e. the names of the rules do not make that obvious at all. To make matters even worse, there are a bunch of shortcut rules that set multiple rules. (In the same way that you can do border: 1px solid blue;.) However, these shortcuts are confusing when first learning how to use display: flex.

Because of all of this complexity, the explanation that follows will cover each main axis type separately. First, a row based flex container will be fully explained, followed separately by a column based one. This explanation will neither cover shortcut rules nor will it include css values that aren't that useful or well supported.

row based flex container

This is where the child elements are placed one after the other in a horizontal row. It can be set up to either wrap child elements to additional rows if they no longer fit (like word wrap does for words), or the children can be set to be stretched to fit the available width of the container based on the flex-grow rules assigned to the individual children.

common examples:

row examples

css rules for the container:

  • display: flex - establishes a block element as a flex container. Do not use 'display: flexbox' as that is deprecated.
  • flex-direction: row - establishes the row axis as the main axis, and the column axis as the cross axis.
  • flex-wrap: nowrap | wrap - indicates if children should wrap to the next row when they hit the right edge of the container
  • justify-content: flex-start | flex-end | center | space-evenly - positions the child elements horizontally along the row axis when there is extra horizontal space
  • align-items: flex-start | flex-end | center | stretch | baseline - positions or stretches the child elements vertically when there is extra vertical space
  • column-gap: <size> - sets minimum horizontal spacing between elements

only for multiple rows:

  • align-content: flex-start | flex-end | center | stretch | space-evenly - stretches or positions the rows themselves vertically when there is available space.
  • row-gap: <size> - sets minimum vertical spacing between rows

row based flex children

css rules for the children:

  • order: <number> - indicates the position in the layout, 1 is the left most element of row 1, 2 is to the right of that, etc. The default order is the declaration order.
  • flex-grow: <number> - lets children's widths grow compared to the other children. Ex. if all the other children have 1, but this child has 2, it will be twice as wide as the others. You can have the last item fill in the available horizontal space in the row by assigning a 1 to flex-grow, and not assigning any flex-grow to the others.

column based flex container

This is where the child elements are placed one under the other in a vertical column. It can be set up to either wrap child elements to additional columns if they no longer fit (like a newspaper), or the children can be set to be stretched to fit the available height of the container based on the flex-grow rules assigned to the individual children.

common examples:

row examples

css rules for the container:

  • display: flex - establishes a block element as a flex container. Do not use 'display: flexbox' as that is deprecated.

  • flex-direction: column - establishes the column axis as the main axis, and the row axis as the cross axis.

  • flex-wrap: nowrap | wrap - indicates if children should wrap upwards to the next column when they hit the bottom of the container

  • justify-content: flex-start | flex-end | center | space-evenly - positions the child elements vertically along the column axis when there is extra vertical space

  • align-items: flex-start | flex-end | center | stretch | baseline - positions or stretches the child elements horizontally when there is extra horizontal space

  • row-gap: <size> - sets minimum vertical spacing between elements

only for multiple columns:

  • align-content: flex-start | flex-end | center | stretch | space-evenly - stretches or positions the columns themselves horizontally when there is available space.

  • column-gap: <size> - sets minimum horizontal spacing between columns

column based flex children

css rules for the children:

  • order: <number> - indicates the position in the layout, 1 is at the top of column 1, 2 is below that, etc. The default order is the declaration order.
  • flex-grow: <number> - lets children's heights grow compared to the other children. Ex. if all the other children have 1, but this child has 2, it will be twice as high as the others. You can have the last item fill in the available vertical space in the column by assigning a 1 to flex-grow, and not assigning any flex-grow to the others.

keep these things in mind

The key to using 'display: flex' correctly is to keep these in mind:

  • keep straight which rules are meant for the flex container and which are meant for the children. (You can see above that most rules are meant for the container.)
  • keep straight how all of the rules work for each of the 2 axis flavors of flex containers: flex-direction: column vs. flex-direction: row

It's especially important to keep these things in mind when child elements can be flex containers in their own right!

css nesting

It's finally here as of September 2023 in all major browsers.

<div class="container1">
  <div class="child">
  </div>
</div>
<div class="container2">
  <div class="child">
  </div>
</div>
.container1 {
  width: 100%;
  .child {
    width: 50%;
  }
}

The above css only affects the .child in .container1, not the .child in .container2.

other posts
personal internet security
what *is* electron?
firewall ip filtering overview
javascript binary data
practical http caching
modern css concepts
my favorite vscode extensions
try import helper for vscode
node coding handbook
the case for electron.js