CSS Basics - Structure

Shawn Werber
5 min readAug 29, 2022

Remember how I mentioned in my HTML Basics - Structure article that most advanced structures would be handled by CSS? Well, this is it.

Photo by sgcdesignco on Unsplash

As I mentioned before, HTML’s ‘table’ element is the only way in HTML alone to get consistent vertical AND horizontal structure, but it is extremely limited. Just as tables have rows and columns, CSS gives us the ability to styles elements with rows and columns of their own. Enter Grid and Flexbox.

Grid

Grid acts like HTML’s ‘table’ but with far more advanced functionality. It can be used to merge ‘cells’ (I am going to be referring to grid elements like they are part of a table going forward, just FYI), define sizes, handle responsive use cases, and much more.

The first and most important thing to remember about grid is that, because it is a CSS command, it must be applied to an HTML element. This won’t just happen magically, so refer to my articles on how CSS works and how to declare styles if you skipped them.

We define grid first by applying the ‘display: grid;’ style to our ‘grid container’. The container can of course be called whatever we desire, but it will always be our container and the elements inside always our ‘grid items’. It should look something like this:

.grid-container {display: grid;}

This simple declaration tells the browser to format all of the elements inside our container into a grid formation with default styles. From here we can define what our container should look like, font sizes and styles, etc. but most importantly, we can specify how large or small the total grid should be by defining how many columns and rows there are.

We do this by declaring the styles ‘grid-template-columns’ and ‘grid-template-rows’. Every individual value you put after this declaration will represent a column/row and its size (width or height, respectively). The following -

grid-template-columns: 80px 100px 20px;

would represent a grid with three columns with their respective widths running left to right. The same procedure applies to rows of course.

Once the grid container has its proper styles, we should define the grid item styles. As with our container these items’ defining class name can be anything. Styles can be applied just like they would to any div or other HTML element to change background color, font size or color, etc.

We define the size of an element in our grid by styling the grid items themselves. By using the style declaration ‘grid-column’ or ‘grid-row’, we can define where the item is to start and end. For example -

.grid-item {grid-column: 1 / 3;}

would result in our grid item spanning the width of the first two columns. This might be confusing, since on the surface it appears that we are telling the grid item to end on the 3rd column, so keep in mind that the ‘column-end’ or ‘row-end’ half of the equation here refers to the column or row we stop before.

This takes a lot of getting used to so take some time to practice both and get a feel for them.

Grids also have the ability to define the size of the gap between elements using the ‘gap’ style. This applies to the gaps between rows and columns, though we can specify rows or columns individually using ‘row-gap’ and ‘column-gap’ respectively.

Flexbox

Flexbox works much like grid but is one-dimensional, differing from grid’s two axis approach. This difference very much exposes the different use cases of the two - if you have a stack of elements you want to structure in two directions use grid, otherwise run your one-direction list using flexbox.

Define a flex container like this -

.flex-container {display: flex;}

You should notice immediately that the elements inside, now ‘flex items’ align nicely in a horizontal fashion. This is the default one-dimensional layout of flexbox, but using the ‘flex-direction’ style, you can change the direction between horizontal and vertical.

We can also define how a flexbox should act when the screen/outer container size becomes too restrictive. The ‘flex-wrap’ property defines whether the items in a flexbox should wrap down to a new line when constricted, or not.

‘flex-flow’ is shorthand for both ‘flex-direction’ and ‘flex-wrap’.

Flex items have their own unique styles too -

By setting the value of the ‘order’ property, flex items can be given their specific place in the hierarchy of a flexbox.

The ‘flex’ property is shorthand for three important size-determining properties — ‘flex-basis’, ‘flex-grow’, and ‘flex-shrink’. They define respectively the starting size, comparative growth rate, and comparative shrink rate of the items they define.

And lastly, we have ‘align-self’. This overrides any alignment done by ‘align-items’ in order to give a specific ‘align-items’ style alignment to itself alone should the need arise. The values of ‘self’ are the same as ‘items’.

Responsive

Flexbox is uniquely good at making responsive formatting easy. Using a media query (more on responsive design later), we can change the flex direction or flex-basis of flex items on demand, changing them depending on screen size. See examples here.

Shared Styles

Grid and Flexbox share the purpose of structuring HTML in a better, more user-friendly way than anything native HTML has to offer. As such, certain styles are shared between the two.

Alignment

The most important and commonly used are the alignment styles. These include ‘justify-content’, ‘align-items’, and ‘align-content’. These define the default alignment of content in containers styles with these.

justify-content’ aligns content horizontally inside its container.

align-items’ aligns content vertically.

align-content’ changes how ‘flex-wrap’ is defined. It works the same as ‘align-items’ but aligns flex lines rather than the items themselves. There must then be more than one line for it to do anything.

The values of the above three are almost all the same, the only difference being in the function itself. flex-start, center, space-evenly, etc. are all shared between all three. I have added links in each property name to examples of all the values each one can use.

--

--