A CSS Deepdive

The idea of this site is to function a little like a tutorial, but maybe not exactly. It's going to be more of a deep dive into certain topics, mostly, initially at least, centered around CSS with some general information about how it works alongside the HTML. Why? Because that's what I'm learning right now. So in fact this is less a tutorial for an absolute beginner —from start to finish, all in an orderly fashion, perfectly digested— and maybe more like my own notes, maybe a little chaotic, not following a perfectly planned structure. But the main idea is to use this as a sort of sandbox, so as I learn I'll apply the knowledge to this site and that way it will be at the same time my notebook and my playground. Smart, no?

'Smort'

One more thing, I'm not exactly an absolute beginner, but I'm also not particularly advanced, not sure if I qualify as intermediate or more like a "false beginner".

Anyway, that's probably enough introduction.

The actual content starts here:

1. Basic formatting

I'll start with a quick review of the basic formatting of the site (this might change in the future).


body {
    background-color: rgb(39, 39, 63);
    padding: 0;
    margin: 0;    
}
#content {
    font-family:Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
    letter-spacing: 2px;
    font-size: 1.2rem;
    color: #ceba9b;
    padding: 2rem;
    max-width: 1200px;
    margin-left: auto;
    margin-right: auto;
}
h1 {
    text-align: center;
    letter-spacing: 4px;
    font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
    color: #caa56c;
}
h2 {
    color: #caa56c;
    padding-left: 1rem;
}
h3 {
    color: #caa56c;
}
img {
    display: block;
    margin: auto;
    width: 50%;
}
.highlight {
    color: #c340b2;
}
.note {
    text-align: center;
    font-family: 'Sometype', Mono;
    font-size: 1rem;
    color:#c340b2;
}
pre {
    font-family: 'Sometype', Mono;
    background-color: rgb(40, 40, 40);
    padding: 2rem;
    margin-top: 1rem;
    margin-bottom: 1rem;
    border: none;
    border-radius: 10px;
    overflow: auto;
    color: rgb(183, 255, 0);
}

@media (max-width: 800px) {
    img {
        width: 80%
    }
    #content {
        font-size: 1.4rem;
        padding: 1rem;
    }
    pre {
        padding: 1rem;
    }
}
            

Note: This is the basic style I'm starting with, but it will likely change a bit as I add more complexity to the site.

Most of this is pretty basic style formatting. There's a background color, font, the h1 is centered, the image is centered, now, you have to tell the image to display as block so you can center it by apllying a margin on all sides. There is a <div> with an id of 'content'

The <pre> tag is maybe not that common for beginners, but you've surely seen it in other coding tutorials. One thing to know about this tag is that once you open the tag, it's important to write the text outside of the normal indentation of your code, so that the formatting works fine, because what it does is eliminate any formatting so the text will appear exactly as it is written in the HTML, including whitespace and line breaks; kind of like this:

    <p>Some random paragraph</p>
    <pre>
Some pre-    
    formatted
        text
    </pre>
    <p>Back to the normal flow of indentation.</p>
            

By default it will display in the system mono space or fixed width font, of course you can customize it like I did with a font from Goolge Fonts.

I included a media querry to give the site some basic responsiveness: when the screen gets narrower, the image occupies a larger percentage, the padding in the #content div and <pre> sections gets smaller, and the font gets a little bigger. I'll probably expand more on media querries and responsiveness later on.

Now I'd like to get into some more meaty topics. I'll start with position property because it's one thing that is absolutely basic, but also merits a deep dive, I believe that if you understand how to use it thoroughly it will save you many headaches later on.

2. Position

There are 5 arguments that the position property can take:

The general idea is: once a position type is set for an element, it can then be moved with the top, bottom, left and right properties, but it will be affected differently depending on the type of position.

static is the default for any element, it is positioned according to the normal flow of the page. You cannot alter it's position with the top, bottom, left and right properties, as in the other position types.

sticky is, well, sticky. That means that depending on your layout, it will appear in one position, and it can move with the rest of the page if you scroll down or up, but it will come to a certain point and "stick" there. The most obvious and common use for this property is navbars. I used top: 3rem;.

relative positioned elements will be positioned relative to their "normal" position in the page flow and you can adjust the position with the same rules, but the next element will still occupy it's own position according to the "normal" position of the relative element before its postion adjustment.

absolute position elements will be positiones relative to their nearest positioned ancestor — that is, the element in which theuy are contained that has a set position argument. If there is none, it will be positioned relative to the document body.

finally, fixed position elements will be positioned relative to the viewport, that is: the screen; and they don't move, they always stay in the same, and they dont leave their "normal" place empty like the relative position elements.

In case you are wondering, I used an iframe element here, to be able to write HTML and CSS code without affecting the rest of the page.

And here's the HTML and CSS code frome the iframe:

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            background-color: black;
            color: white;
            font-family:Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
        }
        div {
            height: 100px;
            background-color: blueviolet;
            padding: 1rem;
            margin: 0.5rem;
        }
        #static-pos {
            background-color: aqua;
            position: static;;
            top: 50px;
        }
        #sticky-pos {
            position: sticky;
            top: 3rem;
            height: auto;
            padding-top: 0;
            padding-bottom: 0;
            border: 2px solid rgb(120, 120, 120)
        }
        #relative-pos {
            position: relative;
            background-color: brown;
            border: 1px solid rgb(120, 120, 120);
            width: 50%;
            top: 50px;
            left: 100px;            
        }
        #absolute-pos {
            position: absolute;
            background-color: rgb(211, 169, 32);
            border: 1px solid rgb(120, 120, 120);
            height: auto;
            top: 60px;
            right: 60px;
            opacity: 0.7;
        }
        #fixed-pos {
            position: fixed;
            bottom: 0;
            width: 30%;
            height: auto;
            background-color: darkslateblue;
            border: 1px solid rgb(120, 120, 120);
            margin: 1rem;
        }
        /*Scrollbar */
        ::-webkit-scrollbar {
            width: 8px;
            height: 8px;
        }
        ::-webkit-scrollbar-track {
            background:#4a4a4a;
        }
        ::-webkit-scrollbar-thumb {
            background: rgb(120, 120, 120);
        }
        ::-webkit-scrollbar-corner {
            background: #4a4a4a;
        }
    </style>
</head>
<body>
    <div id="static-pos">
        <h2>Static position div</h2>
    </div>
    <div id="sticky-pos">
        <h2>Sticky position div</h2>
    </div>
    <div id="relative-pos">
        <h2>Relative position div</h2>
    </div>
    <div style="position: relative">
        <h3>Relative position div containing an absolute positioned div</h3>
        <div id="absolute-pos">
            <h2>Absolute position div</h2>
        </div>
    </div>
    <div id="fixed-pos">
        <h2>Fixed position div</h2>
    </div>   
</body>
</html>
            

3. Measurement units

Is there a perfect unit for each particular use-case, or is it in the end a matter of taste?

There are a bunch of different units and it gets very confusing. There are some that are more suited for general purposes and some that might be better for some specific cases.

Generally speaking, they are divided in absolute and relative units.

Absolute units

Like their name implies, these are units that reflect an absolute measurement unit and they should stay exactly the same no matter the size of your screen, even if you make the window bigger or smaller, and even on different devices with different resolution and dpi.

50 mm
5 cm
2 in
192 px*
144 pt*
12 pc*

* pc and pt are less known. 1 pt = 1/72 in, so that means 144 pt = 2 in; and 1 pc = 12 pt: so 12 pc = 2 in. px or pixel is also 'absolute' in theory, but technically, it is relative to the resolution in your screen; 1px = 1/96th in, so 192 px = 2 in. Capish?


Relative units

These all require a bit more explanation individually.

em is relative to the font size of the parent element. So if I write a <span> with font-size of 2em here, that's 2 times the size of the regular font in a normal paragraph. But if I write an <h1> with the same style...

h1 with 2em font size

That's the same as any normal h1. Why? Because h1 already has a default size of 2em. But if I nest elements with a defined font-size each, the size will compund:

20px text

This div has 1.2 em font-size

This div also has 1.2 em font-size

<div style="border:1px solid; padding: 1em; font-size: 20px">
    <p>20px text</p>
    <div style="border:1px solid; padding: 1em; font-size: 1.2em">
        <p>This div has 1.2 em font-size</p>
        <div style="border:1px solid; padding: 1em; font-size: 1.2em">
            <p>This div also has 1.2 em font-size</p>
        </div>
    </div>
</div>
            

So remember, it is relative to the font size of the parent element —the nearest parent element with a defined font-size— not the default font-size of the element you are aplying the style to. That can get a little unpredictable and it's why they invented rem unit which is more consistent.

rem is always relative to the font-size of the root element, so it's a little more "absolute" in that sense. If I write a <span> of 1 rem font-size here it's smaller than my normal paragraph font because I set a font-size of 1.2 rem in my #content div, so it's referencing back to the default 1em font-size of the body which is 16px.

A p element with 1.5 rem font size

An h1 element with 1.5 rem font-size.

Both elemets here have the same computed font-size in pixels but there are some other differences in the formatting of p and h1 that might make them look a little different.

So no matter where the element is located or what styles it's inheriting, 1 rem will always be the default size of the 'root' element. Of course, you can always change the font size of the 'root' element, that is, the html element in the CSS rules.

For those reasons rem is more commonly used to define font size, because it saves you from tracking down parent font sizes and trying to find out who's inheriting what, but em can be very useful to define things like padding and margins where you sometimes do want the size to be relative to the elements font size.


ex is relative to the x-height of the current font, that is: the height of the lower-case x character:

x a lower-case 2em size x.

a 2ex by 2ex square.


ch is relative to the width of '0'. So it works similar to ex.

0 a 2em size 0 (with a clear background to show full width of the character).

a 2ch by 2ch square.


vw and vh each represent 1% of the viewport's width and height, respectively. So a 50vw by 4 vh line looks like this:

And you can zoom in and out and see how that bar gets smaller or bigger (relative to the document) but stays the same size relative to the screen or window.


vmin and vmax represent, repectively, 1% of the viewport's smaller, or larger dimension; that means it depends on whether your sreen or window is on portrait or landscape mode.

So if you draw a square 10vh by 10vw, it's height will be 10% of the viewport's larger dimension —which if you are on landscape mode is the width, if you are on portrait mode it's th height; and its width will be 10% of the smaller dimension.

You can play around with the width and height or the orientation of the screen and how it adapts; and again, if you zoom in and out and the square will maintain the same absolute dimensions relative to the screen or window.


% is relative to the parent element, depending on wich element you are using it with. That is: if you apply width: 50%, it will be 50% of the parent element's width; if you apply height: 50%, it will be 50% of the parent element's height; or if you apply font-size: 50%, the font will be 50% of the normal font-size for that element.

This div has a height of 30vh

The above bar has 50% width and 10% height*.

This line is a <p> element with 50% font size

There's a catch with with the height property: unless you specify a height for the parent element, giving the child element a height in percentage doesn't work.

That's it for units, the next topic is kind of a big one...

4. Flexbox

This one is rather complex. There are whole websites, even books, dedicated to mastering Flexbox. So perhaps I won't cover all the intricacies, but at least clarify some of the more important issues.

The most important use of Flexbox is for site responsiveness. It gives a container, or the whole page, the ability to adapt to any screen or window ratio without messing up the layout or controlling how the layout changes. But also helps just for organizing elements in a container in a consistent layout.

This is a very basic Flexbox layout. It includes a container which has a few properties related to flexbox. Here's the code:

<div class="demo demo-flex" id="demo-flex1">
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
</div>
                
#demo-flex1 { display: flex; flex-direction: row; width: 100%; justify-content: space-evenly; align-items: flex-start; flex-wrap: wrap; } #demo-flex1 div { height: 100px; width: 100px; background-color: aqua; margin: 0.5em; }

First, the container has to have the display: flex; property, otherwise it's not a flex container, that unlocks all the other superpowers of flexbox —I might do a section about the display property next...

This property defines whether the main axis is the x-axis (row) or the y-axis (column). The default is row, so the main axis is the x-axis, that is, items will be arranged horizontally.

justify-content and align-items define how the items are spaced or distributed inside the flex container along the main axis and the secondary axis respectively. Whether the flex-direction property is set to row or column will determine if these properties affect the horizontal or the vertical axis.


justify-content

This property can take several different values:

1
1
1
2
2
2
3
3
3
4
4
4
5
5
5
6
6
6

The containers are justified in the same order: 1. flex-start; 2. flex-end; 3. center; 4. space-between; 5. space-around; 6. space-evenly

<div class="demo demo-flex" id="demo-justify">
    <div class="demo-justify-content" style="justify-content: flex-start;">
        <div>1</div>
        <div>1</div>
        <div>1</div>
    </div>
    <div class="demo-justify-content" style="justify-content: flex-end;">
        <div>2</div>
        <div>2</div>
        <div>2</div>
    </div>
    <div class="demo-justify-content" style="justify-content: center;">
        <div>3</div>
        <div>3</div>
        <div>3</div>
    </div>
    <div class="demo-justify-content" style="justify-content: space-between;">
        <div>4</div>
        <div>4</div>
        <div>4</div>
    </div>
    <div class="demo-justify-content" style="justify-content: space-around;">
        <div>5</div>
        <div>5</div>
        <div>5</div>
    </div>
    <div class="demo-justify-content" style="justify-content: space-evenly;">
        <div>6</div>
        <div>6</div>
        <div>6</div>
    </div>
</div>
            

align-items

This is similar to justify-content but it distributes items on the secondary axis. It can also take different values.

1
1
2
2
3
3
4
4

5

5

5

  1. flex-start: aligns the items to the start of the secondary axis.
  2. flex-end: aligns the items to the end of the secondary axis.
  3. center: aligns the items at the center.
  4. stretch: stretches the items to occupy all the available space along the secondary axis.
  5. baseline: aligns the baselines of the text of the items inside the flex container. Here I wrote a regular p element, an h1 and an h2 where I removed the top margin, and all the numbers align at their base.
<div class="demo" id="demo-align" style="flex-direction: row;">
    <div class="demo-align-items" style="align-items: flex-start;">
        <div>1</div>
        <div style="height:60px">1</div>
    </div>
    <div class="demo-align-items" style="align-items: flex-end;">
        <div>2</div>
        <div style="height:60px">2</div>
    </div>
    <div class="demo-align-items" style="align-items: center;">
        <div>3</div>
        <div style="height:60px">3</div>
    </div>
    <div class="demo-align-items" style="align-items: stretch;">
        <div>4</div>
        <div style="width:60px">4</div>
    </div>
    <div class="demo-align-items" style="align-items: baseline;">
        <div><p>5</p></div>
        <div><h2>5</h2></div>
        <div><h3 style="margin-top: 0;">5</h3></div>

    </div>
</div>
                
#demo-align { flex-wrap: wrap; justify-content: space-evenly; } .demo-align-items { display: flex; flex-direction: row; height:100px; flex-wrap: wrap; border-top: 1px solid white; border-bottom: 1px solid white; margin: 0.5rem; } .demo-align-items div { background-color: #c340b2; width: auto; padding: 0.5rem; min-width: 30px; border: 1px solid whitesmoke; margin: 0.2rem; }