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?
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:
static
sticky
relative
fixed
absolute
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
cm
mm
in
px
pt
pc
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.
* 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
andrem
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
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
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
andvh
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
vmax
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...
flex-direction
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
andalign-items
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:
flex-start
: this si the default. Aligns the items to the start of the main axis.flex-end
: aligns items to the end of the main axis.center
: packs the items at the center of the axis.space-between
: puts the firts item at the start of the main axis, the last at the end, and distributes the avilable space in between.space-around
: Distributes the items evenly along the axis, but the space before the first and after the last items is equal to half the space between the items. Basically gives each item a margin.space-evenly
: similar tospace around
but it calculates so that the space before the first item and after the last item is the same as the space between the items.
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.
5
5
5
flex-start
: aligns the items to the start of the secondary axis.flex-end
: aligns the items to the end of the secondary axis.center
: aligns the items at the center.stretch
: stretches the items to occupy all the available space along the secondary axis.baseline
: aligns the baselines of the text of the items inside the flex container. Here I wrote a regularp
element, anh1
and anh2
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; }