CSS is a Stylesheet language that changes how HTML documents are styled. It affects font styles, colors, layout and responsive features.
- CSS is made up of rules
- Selector
- Semi-colon
- List of declarations
- Property:Value pair
/* selector */
div.bold-text {
font-weight: 700;
/* property: value; */
}
- Refer to HTML elements to which the CSS rules apply
- What's being selected for each rule
/* styles.css */
* {
color: purple;
}
- Selects elements of the given element type
<!-- index.html -->
<div>Please agree to our terms of service.</div>
/* styles.css */
div {
color: white;
}
- Selects elements with the given class
- Classes are attributes you place on an HTML element
<!-- index.html -->
<div class="alert-text">
Welcome to the machine.
</div
/* styles.css */
.alert-text {
color: red;
}
- Similar to class selectors
- Select elements with a given ID
- Use a hashtag followed by case sensitive ID
- Common pitfall: overusing ID. Classes will suffice most of the time and ID's should be use sparingly (if at all)
- Used when specificity is needed or having links redirect to a section on the current page
- Elements can have only ONE ID & NO WHITESPACE
<!-- index.html -->
<div id="title">Welcome to the machine.</div
/* styles.css */
#title {
background-color: white;
}
- Used with multiple groups of elements that share style declarations
.read,
.unread {
color: white;
background-color: black;
}
.read {
/* several unique declarations */
}
.unread {
/* several unique declarations */
}
- Used to apply styles to a specific combo of selectors
- Must contain all selectors in order for rules to apply
- No space between selectors
- Can't chain multiple
type
selectors (ie: div, p, h1)- Because that would give you
divph1
- Because that would give you
<div>
<div class="subsection header">Latest Posts</div>
<p class="subsection preview">This is where a preview for a post might go.</p>
</div>
/* elements that contain both classes */
.subsection.header {
color: red;
}
/* can mix classes and id's*/
.subsection#preview {
color: blue;
}
- Allow you to combine multiple selectors by their relationship between them
- There are 4 types of combinators in total
- Represented by single space between selectors
- Matches the last selector only
- If they also have an ancestor (parent, grandparent, etc.) that matches the previous selector
.ancestor .child
would select the classchild
if it has the ancestor with the classancestor
- If it is nested inside of ancestor
<!-- index.html -->
<div class="ancestor">
<!-- A -->
<div class="contents">
<!-- B -->
<div class="contents"><!-- C --></div>
</div>
</div>
<div class="contents"></div>
<!-- D -->
In this example, BOTH B & C would be selected.
/* styles.css */
.ancestor .contents {
/* some declarations */
}
- Common keywords (Predefined, Cross-browser)
- ie:
red
,coral
,transparent
- Full List of Pre-defined Colors
- ie:
#p1 {
background-color: red;
} /* red */
#p2 {
background-color: transparent;
} /* transparent */
- HEX values
- ie:
#ff0000
(red) - Specified with
#RRGGBB
RR
: Red valuesGG
: Green valuesBB
: Blue values
- Range:
00
(lowest) toFF
(highest)
- ie:
#p1 {
background-color: #ff0000;
} /* red */
#p2 {
background-color: #00ff00;
} /* green */
#p3 {
background-color: #0000ff;
} /* blue */
- HEX values with transparency
- ie:
#ff000080
- Transparency: Add 2 digitals between
00
&FF
- ie:
#p1a {
background-color: #ff000080;
} /* red transparency */
#p2a {
background-color: #00ff0080;
} /* green transparency */
#p3a {
background-color: #0000ff80;
} /* blue transparency */
- RGB values
- ie:
rgb(red, green, blue)
rgb()
is a function- Intensity of each value: 0 (lowest) to 255 (highest)
- ie:
#p1 {
background-color: rgb(255, 0, 0);
} /* red */
#p2 {
background-color: rgb(0, 255, 0);
} /* green */
#p3 {
background-color: rgb(0, 0, 255);
} /* blue */
- RGBA values
- ie:
rgba(red, green, blue, alpha)
- RGB colors with an alpha channel
- Specifies opacity of the object
- Alpha: 0.0 (fully transparent) to 1.0 (opaque)
- ie:
#p1 {
background-color: rgba(255, 0, 0, 0.3);
} /* red with opacity */
#p2 {
background-color: rgba(0, 255, 0, 0.3);
} /* green with opacity */
#p3 {
background-color: rgba(0, 0, 255, 0.3);
} /* blue with opacity */
- HSL values
- ie:
hsl(hue, saturation, lightness)
- Cylindrical-coordinate representation of colors
hsl()
is a function- Hue: Color Wheel
0
-360
- Red:
0
or360
- Green:
120
- Blue:
240
- Red:
- Saturation: Percentage value
- Shade of gray:
0%
- Full color:
100%
- Shade of gray:
- Lightness: Percentage value
- Black:
0%
- White:
100%
- Black:
- ie:
#p1 {
background-color: hsl(120, 100%, 50%);
} /* green */
#p2 {
background-color: hsl(120, 100%, 75%);
} /* light green */
#p3 {
background-color: hsl(120, 100%, 25%);
} /* dark green */
#p4 {
background-color: hsl(120, 60%, 70%);
} /* pastel green */
- HSLA values
- ie:
hsla(hue, saturation, lightness, alpha)
- Alpha parameter:
0.0
-1.0
- Fully transparent:
0.0
- Fully Opaque:
1.0
- Fully transparent:
- ie:
#p1 {
background-color: hsla(120, 100%, 50%, 0.3);
} /* green with opacity */
#p2 {
background-color: hsla(120, 100%, 75%, 0.3);
} /* light green with opacity */
#p3 {
background-color: hsla(120, 100%, 25%, 0.3);
} /* dark green with opacity */
#p4 {
background-color: hsla(120, 60%, 70%, 0.3);
} /* pastel green with opacity */
- Color property: text color
- Background-Color property: background color of an element
p {
/* hex example: */
color: #1100ff;
/* rgb example: */
color: rgb(100, 0, 127);
/* hsl example: */
color: hsl(15, 82%, 56%);
}
font-family
can be single value, or comma-separated list for fonts- Falls into 1 of 2 categories:
- Font Family Name:
Times New Roman
- Generic Family Name:
sans-serif
have clean lines, modern, minimal- ie: Arial, Verdana, Helvetica
serif
are formal, elegant, have small stroke at edge of each char- ie: Times New Roman, Georgia, Garamond
monospace
have fixed width, mechanical look- ie: Courier New, Lucida Console, Monaco
cursive
imitate human handwriting- ie: Brush Script MT, Lucida Handwriting
fantasy
are decorative, playful- ie: Copperplate, Papyrus
- Font Family Name:
- If browser can't find 1st font in list, it will use the next one
- Best Practice: Include list of values, starting with top preference, and ending with least preferred
font-family: "Times New Roman", sans-serif;
font-family: "Times New Roman", Times, serif;
font-family: Arial, Helvetica, sans-serif;
font-family: "Lucida Console", "Courier New", monospace;
@font-face
is used for loading custom fonts in browser & present it to site- Must appear before other styling properties
- Requires 2 properties:
font-family
font namesrc
URL to download the font
@font-face {
font-family: fontname;
src: url(https://fonts.gstatic.com/s/lato/v16/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2);
font-weight: italic;
}
- Alternative: Linking fonts in the
<head>
<head>
<link
href="https://fonts.googleapis.com/css?family=Gayathri&display=swap"
rel="stylesheet"
/>
</head>
- Alternative: Importing fonts using
@import
to css
@import url("https://fonts.googleapis.com/css?family=Gayathri&display=swap");
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter" />
font-size
should contain NO whitespace
font-size: 22px;
font-weight
affects boldness of text- Values can be:
- the word
bold
or a value between1
-1000
- Typically in increments of
100
up to900
, depending on the font:200
,300
,400
bold
word equivalent:700
- the word
font-weight: 700;
text-align
aligns text horizontally within an element- Common keywords:
center
,right
,left
text-align: center;
- Default
<img>
size = actual image'sheight
&width
auto
value will automatically adjust size of an image without causing it to lose its proportions
img {
height: auto;
width: 500px;
}
- If the above image had a height of
500px
and width of1000px
auto
would downsize theheight
to250px
- Best Practices
- ALWAYS include both height & width for ALL images
- Reserves space on the page & will appear blank until image loads
- If
height
&width
are not included & the image takes longer to load than the rest of the page, the image will not take up any space on page at first - Will suddenly cause a drastic shift of the other page contents once loaded
- Sometimes rules conflict with one another
- CSS does what we tell it to do
- Unexpected behavior can occur due to:
- Default styles vary from browser to browser
- ie: Large gaps between elements, button styles, etc. can appear on it's "own"
- Not understanding
the cascade
or how aproperty
works
- Default styles vary from browser to browser
- The CSS Cascade is the way our browsers resolve competing CSS declarations.
- Importance
- transition - active transitions are #1
!important
- reserve for overriding 3rd party libraries- animation - active animation
- normal - bulk of rules
- Origin, where rules are defined
- website: in your control as web developer
- user
- browser: each browser has its own set of default styles
- Specificity
- Position, rule order
- Importance
- If two or more CSS rules that point to the same element, the selector with the highest specificity value will "win", and its style declaration will be applied to that HTML element.
- Creates a score or ranking system
- More specific CSS declarations > less specific CSS declarations
- Specificity only matters when elements have multiple, conflicting declarations (a tie breaker):
- Hierarchy
- Inline
<h1 style="color: white">
- Layers unlayered > layered
@layers one, two;
- ID selectors
#navbar
- Class
.class
, Attribute Selectors[href]
or[checked]
, Pseudo Selectors:hover
or:first-of-type
- Type or Pseudo-eEement selectors
h1
or:before
- Inline
<div class="main">
<div class="list subsection"></div>
</div>
Multiple classes > Single class
/* rule 1 */
.subsection {
color: blue;
}
/* rule 2 -- MORE SPECIFIC */
.main .list {
color: red;
}
<div class="main">
<div class="list" id="subsection"></div>
</div>
ID selector > Multiple Class selectors
/* rule 1 -- MORE SPECIFIC */
#subsection {
color: blue;
}
/* rule 2 */
.main .list {
color: red;
}
1 ID & 2 Class Selectors > 1 ID & 1 Class Selector
/* rule 1 */
#subsection .list {
background-color: yellow;
color: blue;
}
/* rule 2 -- MORE SPECIFIC */
#subsection .main .list {
color: red;
}
Chaining Selector (no space) & Descendant Combinator (empty space) DO NOT AFFECT specificity
/* rule 1 -- SPECIFICITY EQUAL TO rule 2 */
.class.second-class {
font-size: 12px;
}
/* rule 2 -- SPECIFICITY EQUAL TO rule 1 */
.class .second-class {
font-size: 24px;
}
Universal selector *
and Combinators +
, ~
, >
,
(empty space) DO NOT ADD specificity
/* rule 1 -- NO SPECIFICITY */
* {
color: black;
}
/* rule 2 -- MORE SPECIFIC (Type selector) */
h1 {
color: orange;
}
- CSS Properties, when applied to an element, are inherited by the element's descendants
- Even if we don't explicitly write a rule for it
- Typography based properties ARE USUALLY inherited
- Most OTHER properties AREN'T inherited
Exception: Directly targeting an element > inheritance
<!-- index.html -->
<div id="parent">
<div class="child"></div>
</div>
/* styles.css */
/* Inherited */
#parent {
color: red;
}
/* Directly targeted -- TAKES PRECEDENCE */
.child {
color: blue;
}
- Final factor in a tie-breaker
- If multiple conflicting rules target an element
- The last defined rule is the winner
<div class="alert warning"></div>
.alert {
color: red;
}
/* defined last, takes precedence */
.warning {
color: yellow;
}
- Most common method
- Create a separate file for CSS
- Link to inside HTML's
<head>
tag with the<link>
element- ie:
<link rel="stylesheet" href="styles.css">
href
is the location of the CSS filerel
specifics relationship between HTML & linked file
- ie:
- Pros of external css:
- HTML & CSS are separate, smaller HTML, cleaner look
- Edit CSS in only 1 place, handy for multiple pages that share similar styles
<!-- index.html -->
<head>
<link rel="stylesheet" href="styles.css" />
</head>
/* styles.css */
/* declaration block */
div {
/* selector */
/* declarations */
color: white;
/* color: property */
/* white: value */
background-color: black;
}
/* declaration block */
p {
/* selector */
/* declarations */
color: red;
/* color: property */
/* white: value */
}
- Add CSS within HTML doc itself
- Place all rules inside
<style>
tags, within the<head>
of the HTML file- No longer require
<link>
tag
- No longer require
- Useful for adding unique styles to a single page
- Causes HTML files to be larger
<head>
<style>
div {
color: white;
background-color: black;
}
p {
color: red;
}
</style>
</head>
<body>
...
</body>
- Add CSS tags directly to HTML elements
- Added with the
style=
attribute - Used when you need a
unique
style for asingle
element - NOT recommended:
- Gets messy quickly, bloated
- If you want to share styles among elements, it requires a lot of copy and pasting
- Inline CSS overrides all other methods, causing unexpected results
- Inspecting & Debugging HTML/CSS is criticial to frontend development
- Chrome Dev Tools is used to see detailed info & assists in finding/fixing problems in code
- To access the inspector in Google Chrome
Right Click
on element & clickInspect Element
CTRL+SHIFT+C
to Inspect Elements on hoverF12
CTRL+SHIFT+I
to open the last panel you had openArrow Keys
to go up/down and expand elements in DOMRight Click
on element within DOM andScroll into view
to hop to it's location on the pageH
hides currently selected nodeDelete
deletes currently selected node
- HTML: Initial page contents
- DOM: current page contents
- Blue top left arrow icon: inspect any element on hover
- Elements: HTML
- Styles: CSS Rules
Strikethrough- overwritten style
- Styles pane allows you to directly edit in your browser
- Add new rules
- Edit existing rules
- Changes apply in real-time
- Does NOT affect source code
- Extremely useful for testing out various attributes & values without having to reload page over and over
CTRL+F
Find things in DevTools
- Simulate mobile devices
- View & change DOM & CSS
- View messages & run JavaScript from the Console
CTRL+SHIFT+J
- Debug JavaScript
- Persist changes made in DevTools across page reloads
- Save & run snippets of JavaScript
- Save changes you make in DevTools to disk
- View & debug network activity
- Find ways to improve load & runtime performance
- Fix memory problems
- JavaScript CPU Profiler
- Inspect all resources that are loaded
- IndexedDB or Web SQL databases
- Local & Session Storage
- Cookies
- Application Cache
- Images
- Fonts
- Stylesheets
- Debug
- Mixed content issues
- Certificate problems, etc.
CTRL+SHIFT+I
, click 3 dot icons >More tools
>CSS Overview
- Click
Capture Overview
- Menu Options
- Overview Summary
- Number of Elements used
- Selector types
- Number of inline style elements
- Number of external stylesheets
- Colors
- Each color is clickable
- Shows which elements use each color
- Font Info
font-size
,line-height
,font-weight
,font-family
- Where they're used
- Unused declarations
- Styles that don't affect the web page
- Media Queries
- Various widths & screen resolutions used in creating the page
- ie:
screen
and(max width:736px)
- Overview Summary
- Most important CSS skills: positioning & layout
- JavaScript is meaningless if you can't stick elements on the page where you need them
- Every single thing on page is a rectangular box
- Boxes can have other boxes in them and can sit next to one another
/* To test the box model: */
* {
border: 2px solid red;
}
Parts of a box
- Manipulating boxes & space between them:
border
, space between margin & paddingpadding
, space between edge of box & content- inside the border
- includes
background-color
margin
, space between box & any other boxes next to it- collapse between two elements
- highest
margin
value wins - outside of the border
- not affected by
background-color
height
,width
size of inner element
- "True" height of an element, add all values:
padding
top & bottomborder
top & bottomheight
box-sizing: border-box;
- Almost always added to CSS
- Makes stylizing easier
- Added to universal selector (
* { }
) - Ensures
height
andwidth
are obeyed
Standard CSS Box Model
Border-Box in CSS
In CSS, there are two types of boxes. The type refers to how the box behaves in terms of page flow and in relation to other boxes.
- Block
display: block
- Appear stacked atop each other
- Each new element creates a new line
- Fills available inline space of the parent element and grows along the block dimension to accommodate its content
- Centering a block:
margin: auto
- Inline
- Sizes according to its content
- Sits inside content of block-level elements
- Do not start a new line
- Appear in line with with elements they are placed beside
- ie:
<a>
- Generally, don't add extra padding/margin on inline elements
- Inline-block elements
- Behave like inline elements
- Have block-style padding & margin
- Useful, but
flexbox
is better for lining up boxes
Boxes then have an inner and outer display type.
-
block
outer display types:- Break onto a new line
- Width & Height are respected
- Other elements will be pushed away using padding, margin, border
- Box extends in inline direction to fill space available in container
- Become as wide as it's container, 100% of the space
- ie:
<h1>
and<p>
useblock
by default
-
inline
outer display types:- Will NOT break onto a new line
- Width & Height are NOT applied
- Vertical padding, margins, border WILL apply
- WON'T push other inline boxes away from the box
- Horizontal padding, margins, borders WILL apply
- WILL push other inline boxes away from the box
- ie:
<a>
,<span>
,<em>
,<strong>
Inner display types dictate how elements inside that box are laid out.
- Default: Elements inside a box are laid out in:
- normal flow
- Behave as
block
orinline
- Change inner display type with
display: flex;
- Still uses outer display type
block
- Inner display type
flex
- Still uses outer display type
- DON'T give meaning to their content
- Generic boxes that can do anything
- Used to hook elements
- Give
id
orclass
to them for CSS styling - Grouping related elements under one parent element to correctly position them on the page
- Give
- Block-level element by default
- Used as a container to group other elements
- Divs allow us to divide pages into blocks and apply styles to those blocks
- Inline-level element by default
- Group text content and inline HTML elements for styling
- Should only be used when no other semantic HTML element is appropriate
- Default layout of elements in the Box Model
- Block-level elements
<address><article><aside><blockquote><canvas><dd><div><dl><dt><fieldset><figcaption><figure><footer><form><h1>-<h6><header><hr><li><main><nav><noscript><ol><p><pre><section><table><tfoot><ul><video>
- Inline-level elements
<a><abbr><acronym><b><bdo><big><br><button><cite><code><dfn><em><i><img><input><kbd><label><map><object><output><q><samp><script><select><small><span><strong><sub><sup><textarea><time><tt><var>
- Flexbox is a way to arrange items into rows and columns
- Based on simple rules you can define
- Fill available area w/ equal width
<div class="flex-container">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
.flex-container {
display: flex;
/*
flex-direction: row
> start from edge of main axis
> does not grow on main dimension, but can shrink
>
/*
}
/* this selector selects all divs inside of .flex-container */
.flex-container div {
background: peachpuff;
border: 4px solid brown;
height: 100px;
flex: 1;
}
- Flexbox is a toolbox of properties to put things where you need them
- Any element can be a BOTH a flex container & flex item
- Flex Containers:
display:flex
- Flex items:
flex: 1
- Creating/nesting multiple flex containers and items is the primary way we will be building up complex layouts
/* flex containers */
.container {
display: flex;
display: inline-flexinline;
}
flex
declaration: shorthand for 3 properties- shorthand: CSS properties that allow you to set values of multiple other properties simultaneously
flex: flex-grow, flex-shrink, flex-basis;
flex: 0, 1, 0%;
flex: flex-grow, *, *
- Single number
- Flex-item's Growth Factor
flex: 1;
To all DIV's = grow the same amountflex: 2;
To 1 DIV = 2x the size asflex: 1;
- Similar to
flex-grow
- Flex-item's Shrink Factor
- Only applied if size of ALL flex items is larger than their parent
- Default:
flex-shrink: 1;
- ie: all items shrink evenly
- If 3 DIV's had
width: 100px;
and their container was smaller than300px
, the DIV's would have to shrink to fit - NO Shrink:
flex-shrink: 0;
- Faster Shrink:
flex-shrink: 2(+);
flex-grow
andflex-shrink
do NOT necessarily obey width rules (ie:250px
)if parent is big enough, they grow to fill it
if parent is too small, they shrink to fit
- Sets initial size of a flex item
- Grow/shrinking starts from this baseline
- Default shorthand value:
0%
- ie:
flex: 1
is equal toflex: 1 1 0%;
- ie:
- If you want to only adjust an item's flex-grow
- Default value of
flex-basis
isauto
UNLESS you specifyflex: 1;
flex-basis: auto;
checks for a width declaration
flex: auto;
is equal toflex: 1 1 auto;
(check for width)flex: 1;
is equal toflex: 1 1 0%
(ignore width)
/* grow evenly */
flex: 1;
/* prevent shrinking */
flex-shrink: 0;
- Flexbox can work horizontally or vertically
- Rows or Columns
- Default: horizontal (row)
- Alternative: vertical (column)
- ie:
css .flex-container { flex-direction: column; }
- ie:
- Alternative: vertical (column)
/* default setting */
flex-direction: row;
flex-direction: row-reverse; /* right to left */
/* columns/vertical flexbox */
flex-direction: column;
flex-direction: column-reverse; /* down to up */
- When
flex-direction: column;
is used,flex-basis
refers toheight
- To space objects out within a container, you would add
justify-content: space-between;
.container {
display: flex;
justify-content: space-between;
}
- To center objects within a container, you would add:
- X-axis (horizontally):
justify-content: center;
- Y-axis (vertically):
align-items: center;
- X-axis (horizontally):
.container {
display: flex;
align-items: center;
justify-content: center;
}
gap
adds space between flex items
- Multi-line flex containers
/* default */
flex-wrap: nowrap;
/* move to item to next line */
flex-wrap: wrap;`
- Combine flex direction & wrap into one line
flex-flow: flex-direction, flex-wrap;
/* example */
flex-flow: row wrap;
* {
/* bxz */
box-shadow: inset hoff voff blur #000;
/* ts */
text-shadow: hoff voff blur #000;
/* bd */
border: 1px solid #000;
/* c */
color: #000;
/* bgc */
background-color: #fff;
/* c */
color: #000;
/* df */
display: flex;
/* jc */
justify-content: start;
/* ai */
align-items: start;
/* ta */
text-align: left;
/* m:a */
margin: auto;
}
CSS Resets are used to deal with styling inconsistencies across browsers.
Most popular reset is the Meyer reset. It removes default styling.
HTML5 Reset is a more modern reset based on the Meyer reset.
Normalize.css doesn't remove default CSS styles, but replaces them with a standardized set of rules.
List of alternatives:
- Vanilla CSS Un-Reset: Re-styles elements after you un-style them w/ a reset.
- MiniReset.css: Wipes out styles, semantic markup has no affect, retains some defaults
- Sanitize.css: Modern best practices, opinionated
Reboot
- Reboot: SCSS, Part of bootstrap repo, builds upon Normalize. Opinionated, additional class-specific styles.
Browserlist
Absolute units remain the same in any context. Pixels (px
) is the only absolute measurement used in web design and they do not change relative to anything else on the page.
Relative units change based on their context.
Both em
and rem
refer to font size but are often used to define other sizes in CSS.
Use rem
as a rule of thumb.
1em
is the font-size
of an element (or the element's parent if you're setting font-size
).
If an element's font-size: 16px
, setting width: 4em
would make it's width 64px
because (16px * 4)
.
1rem
is the font-size
of the root element: :root
or html
. It works the same as em
but without having to keep track of the parent's font size.
vw
and vh
relate to the size of the viewport.
1vh
= 1%
of viewport height.
These are useful for full-height heroes, full-screen app-like interfaces.
<integer>
is a whole number: 1024
-55
<number>
is a decimal number: 128
123.11
-0.55
<dimension>
is a <number>
with a unit attached to it: 45deg
5s
10px
. <dimension>
is an umbrella category for:
<length>
<angle>
<time>
<percentage>
ch
= width of the font's0
character.lh
= line height of an elementvmin
= % of viewport's width or height (whichever is smaller)vmax
= % of viewport's width or height (whichever is larger)
Cody recommends using rem
for fonts and px
for everything else.
It's a matter of design preference. When setting margins/paddings to rem
, they will increase in size as the user zooms in.
Setting margings/padding to px
and fonts to rem
will allow the text to grow, but everything else will remain static.
Responsive Typography
Using viewport units for responsive typography is becoming popular, because it allows text to grow/shrink based on the size of the browser window.
Direct scaling is too dramatic, so developers use calc()
to control it. For example, font-size: calc(16px + 0.5vw)
.
Line height is another use case for viewport units.
body {
/* font grows 1px for every 100px of viewport width */
font-size: calc(16px + 1vw);
/* leading grows along with font, */
/* with an additional 0.1em + 0.5px per 100px of the viewport */
line-height: calc(1.1em + 0.5vw);
}
Full-Height Layouts, Hero Images, Sticky Footers
Full Height:
height: 100vh
constrains your web app to the height of your viewport. Make sure to apply overflow
values on internal elements to prevent content from being cut off.
(overflow-y: auto;
)
Sticky Footers:
min-height: 100vh
will make your footer remain at the bottom of your page.
Hero Images:
Apply height: 100vh
for full-screen sections and hero images.
Fluid Aspect Ratios
Constraining height-to-width ratios of an element can be useful (ie: embedded content).
For full-screen videos:
/* full-width * aspect-ratio */
.full-width {
width: 100vw;
height: calc(100vw * (9 / 16));
}
Breaking the Container
To allow full width backgrounds to spill outside of a restricted container:
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
System Font Stack
If a font-family
that isn't installed on a user's computer, a fallback font is displayed. This is why a long list of fonts are often listed.
A popular stack is the system font stack, which defaults to the operating system's UI font.
Useful when going for a "neutral" font-style
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
Online Font Libraries
Using fonts that are not stored on a user's computer is done through font libraries:
To add them to a site, use one of the following:
Always add a backup font
<link rel="preconnect" href="https://fonts.googleapis.com" />
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
Downloaded Fonts
You can also import and define custom fonts using the @font-face
rule. Note: Not all font file formats are supported by browsers.
@font-face {
font-family: my-cool-font;
src: url(../fonts/the-font-file.woff);
}
Text Styles
font-style
<em>
allows you to italicize text in the middle of a sentence but it also adds emphasis to that text.
If you just want text to be bold, italic, underlined or highlighted, use a CSS property.
If you want to provide emphasis, use an html element.
h1 {
font-style: italic;
}
letter-spacing
Some fonts have too little or too much spacing between letters. To change this, use:
h1 {
letter-spacing: 0.5em;
}
line-height
Line height adjusts the space between lines of text and increasing it improves readability.
p {
line-height: 1.5;
}
text-transform
Text transform allows you to change the letter case.
p {
text-transform: uppercase;
text-transform: lowercase;
text-transform: capitalize;
}
text-shadow
Text shadow is good for headers, etc.
h1 {
/* offset-x | offset-y | blur-radius | color */
text-shadow: 1px 1px 2px black;
/* color | offset-x | offset-y | blur-radius */
text-shadow: #fc0 1px 0 10px;
/* offset-x | offset-y | color */
text-shadow: 5px 5px #558abb;
/* color | offset-x | offset-y */
text-shadow: white 2px 5px;
/* offset-x | offset-y
/* Use defaults for color and blur-radius */
text-shadow: 5px 10px;
}
ellipsis
text-overflow: ellipsis
combined with a few other css rules can allow you to insert an ellipsis instead of overflowing out of an element:
.overflowing {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Background is a shorthand property for 8 different background related properties:
background-attachment
background-clip
background-color
background-image
background-origin
background-position
background-repeat
background-size
Syntax:
/* Using a <background-color> */
background: green;
/* Using a <bg-image> and <repeat-style> */
background: url("test.jpg") repeat-y;
/* Using a <box> and <background-color> */
background: border-box red;
/* A single image, centered and scaled */
background: no-repeat center/80% url("../img/image.png");
/* Global values */
background: inherit;
background: initial;
background: revert;
background: revert-layer;
background: unset;
The background property is specified as one or more background layers, separated by commas.
Border is a shorthand property for:
border-color
border-style
border-width
Border Syntax:
/* style */
border: solid;
/* width | style */
border: 2px dotted;
/* style | color */
border: outset #f33;
/* width | style | color */
border: medium dashed green;
border-radius
adds rounded corners.
box-shadow
adds a shadow around an element's frame and it accepts multiple values:
- inset
- offset-x
- offset-y
- blur-radius
- spread-radius
- color
/* Keyword values */
box-shadow: none;
/* offset-x | offset-y | color */
box-shadow: 60px -16px teal;
/* offset-x | offset-y | blur-radius | color */
box-shadow: 10px 5px 5px black;
/* offset-x | offset-y | blur-radius | spread-radius | color */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
/* inset | offset-x | offset-y | color */
box-shadow: inset 5em 1em gold;
/* Any number of shadows, separated by commas */
box-shadow: 3px 3px red, -1em 0 0.4em olive;
Overflow is a shorthand property that sets the behavior when an element's content is too big to fit in its block formatting context.
visible
allows content to spill outside padding box.
hidden
hides or clips content that doesn't fit, and the content is scrollable.
clip
is similar to hidden
but doesn't allow scrolling.
scroll
clips content to fit inside the padding box, and shows scrollbars.
auto
adds scrollbars on desktop. Looks the same as visible
but still establishes a new block formatting context.
overlay
is the same as auto
but with scrollbars drawn on top of content instead of taking up space.
/* Keyword values */
overflow: visible;
overflow: hidden;
overflow: clip;
overflow: scroll;
overflow: auto;
overflow: hidden visible;
Opacity sets opacity of an element, or the degree to which content behind an element is hidden.
opacity
is the opposite of transparency.
/* opaque */
opacity: 1;
/* transparent */
opacity: 0;
Exercise: CSS Diner
Cheatsheet: freeCodeCamp
Parent & Sibling Combinators
>
Child combinator+
Adjacent Sibling combinator- Only the 1st match
~
General Sibling combinator- All siblings
/* all direct children div elements */
main > div {
}
/* all direct grandchildren div elements */
main > div > div {
}
/* only elements on same level of indentation (adjacent) */
/* 1st div that directly follows .group1 */
.group1 + div {
}
/* 2nd div that directly follows .group1 */
.group1 + div + div {
}
/* all div siblings/adjacent to .group1 */
.group1 ~ div {
}
Pseudo-classes give us different ways to target elements. Some are based on:
- Their position or structure within HTML
- State of an element
- How user is currently interacting with it
Pseudo-classes share the same specificity as regular classes: 0,0,1,0
.
Specificty notation:
inline, id, class, tag
, +1 per instance
Dynamic/User Action Pseudo-classes
:focus
element is selected by user via cursor OR keyboard
:hover
anything under mouse pointer
:active
anything currently being clicked: great for giving user feedback that their action had an effect.
Hyperlinks are blue and turn purple after clicking them:
/* This rule will apply to all links */
a {
text-decoration: underline;
}
/* This will apply to unvisited links */
a:link {
color: blue;
}
/* And you guessed it, this applies to all links the user has clicked on */
a:visited {
color: purple;
}
UI element states pseudo-classes
:enabled
:disabled
:checked
Structural Pseudo-classes
Structural pseudo-classes are a powerful way to select elements based on their position within the DOM.
:root
very top level of your document. equivalent to html
(web), with higher specificity.
- place global CSS rules in
:root
(anything you want available everywhere)- css variables
box-sizing: border-box
:first-child
:last-child
match elements that are the first or last sibling.
:empty
matches elements that have no children at all.
:only-child
matches elements that don't have any siblings.
:nth-child
flexible with several uses:
.myList:nth-child(5) {
/* Selects the 5th element with class myList */
}
.myList:nth-child(3n) {
/* Selects every 3rd element with class myList */
}
.myList:nth-child(3n + 3) {
/* Selects every 3rd element with class myList, beginning with the 3rd */
}
.myList:nth-child(even) {
/* Selects every even element with class myList */
}
:nth-of-type(x)
matches the x instance of a selector.
div:nth-of-type(2)
matches the 2nd div in the domdiv:nth-of-type(2n)
matches every 2nd div: div DIV div DIVdiv:nth-of-type(2n+2)
matches every 2nd div, starting at the 2 position: div div div DIV div DIV
:nth-last-of-type(x)
does the same thing as :nth-of-type
, starting at the end of the DOM, working upwards
:target
matches URI fragment identifiers:
section:target {
}
<a href="#cta">Call To Action</a>
<!-- matches url.com/#cta-->
<section id="cta"></section>
:empty
matches elements that don't contain any children
:not(x)
matches elements that don't contain x
div:not(.cta)
matches all divs that don't have a class ofcta
Pseudo-elements
Pseudo-elements are more abstract than pseudo-classes. They allow us to affect parts of our HTML that aren't elements at all.
Specificity of pseudo-elements: 0,0,0,1
::marker
changes li's bullets/numbers style
::first-letter
::first-line
changes styling to first letter/line of text.
::selection
change highlighting when a user selects text on page
::before``::after
adds extra elements with CSS, without the need for HTML. These allow you decorate text in many ways:
<style>
.emojify::before {
content: "😎 🥸 🤓";
}
.emojify::after {
content: "🤓 🥸 😎";
}
</style>
<body>
<div>Let's <span class="emojify">emojify</span>this span!</div>
</body>
Attribute Selectors
Attribute examples: src='picture.jpg'
href="bmilcs.com"
Attribute selector specificity: 0,0,1,0
Basic usage:
[attribute]
targets anything where the attribute existsselector[attribute]
targets a selector with an attribute[attribute="value"]
targets an exact value[attribute~="value"]
targets a whitespace separated list of words, where one of the words is exactly the specified value.[attribute|="value"]
targets exact match OR starts the specified value followed by -attribute="value-one"
orattribute="value"
Regex can be used with attribute selectors to select partial matches:
[attribute^="value"]
matches values that begin with "value"[attribute$="value"]
matches values that end with "value"[attribute*="value"]
matches values that contain "value" anywhere
Examples:
a {
color: blue;
}
/* Internal links, beginning with "#" */
a[href^="#"] {
background-color: gold;
}
/* Links with "example" anywhere in the URL */
a[href*="example"] {
background-color: silver;
}
/* Links with "insensitive" anywhere in the URL,
regardless of capitalization */
a[href*="insensitive" i] {
color: cyan;
}
/* Links with "cAsE" anywhere in the URL,
with matching capitalization */
a[href*="cAsE" s] {
color: pink;
}
/* Links that end in ".org" */
a[href$=".org"] {
color: red;
}
/* Links that start with "https" and end in ".org" */
a[href^="https"][href$=".org"] {
color: green;
}
Learn CSS Position in 9 Minutes
Static is the default positioning mode for all elements.
position: static
top
right
bottom
left
z-index
have NO EFFECT with static positioning.
Relative positioning gives top
right
(etc.) the ability to displace the element relative to its normal position.
position: relative
- Meaning: "relative to itself"
- Has no effect until
top
left
z-index
etc. are added - Makes a parent element the reference point for children with absolute positioning
Absolute positioning lets you position something at an exact point on the screen without disturbing elements around it.
- Removes the element from the normal document flow while being positioned relative to an ancestor element.
- Common use cases:
- Modals
- Image w/ caption on it
- Icons on top of other elements
Fixed elements are removed from the normal flow of the document and positioned relative to the viewport
.
top
bottom
left
right
properties position it and it remains in position while the user scrolls.- Common use cases:
- Navigation bars
- Floating chat buttons
Sticky elements act like normal elements until you scroll past them, then they start to behave like fixed elements.
- Are not taken out of the normal flow of the document.
- Stay within its parent element. If you scroll beyond the parent, it disappears.
- Common use cases:
- Section headings
Practical Uses of CSS Math Functions
CSS Properties that end with a pair of parenthesis and a value between them are called CSS Functions.
Functions are reusable pieces of code which perform specific tasks. They are passed "arguments" between parenthesis, which are used by the function in a specific way.
color: rgb(0, 42, 255);
background: linear-gradient(90deg, blue, red);
The color
property's value is the function rgb()
, which accepts numbers for its arguments. It processes those numbers to calculate the correct color.
The background
property's value is the function linear-gradient()
, which is a function that generates a gradient image based on the parameters it's given.
CSS does NOT allow us to create OUR OWN functions. CSS is bundled with premade functions to help solve the most common styling problems.`
CSS Functions for Responsive Design
There are several CSS functions that help with creating a responsive design.
Most powerful use cases for calc are:
- Mixing Units
- Ability to nest
calc(calc() - calc())
This example shows how
calc()
can affect layout, but it's not the best way to go about it.
:root {
--header: 3rem;
--footer: 40px;
--main: calc(100vh - calc(var(--header) + var(--footer)));
/* pseudocode: */
main = 100% viewport height - (header's height + footer's height)
}
Both min
& max
are great for creating responsive websites.
min
selects the smallest value in its list of parameters
- behaves as a boundary for the
maximum
allowed value - useful for
- limiting size of container
min(400px, 50%)
- 400px on large screens, 50% on small screens
- limiting size of container
max
selects the largest value in its list of parameters
- behaves as a boundary for the
minimum
allowed value - most useful when the
- viewing window is exceptionally small
- the user increases the content size by using the browser's zoom feature
- when accesibility is important
- Basic math can be done within within min/max's parameters
width: min(150px, 100%);
height: min(150px, 100%);
- if 150px is smaller than 100% of the parent's width/height, 150px is used.
- if 100% of the parent's width/height is smaller than 150px, 100% is used.
width: max(100px, 4em, 50%);
- largest value wins: 100px, 4em, 50%
/* basic math example */
min(80ch, 100vw - 2rem);
- smallest value is selected: 80ch OR 100vw - 2rem
clamp
is another great way to make elements fluid & responsive. It accepts 3 values:
h1 {
font-size: clamp(320px, 80vw, 60rem);
}
- Smallest acceptable value (320px)
- Ideal value (80vw)
- Largest value (60rem)
Anything from 45 to 75 characters is widely regarded as a satisfactory length of line for text:
p {
width: clamp(45ch, 50%, 75ch);
}
Alternatively, if you want an element to be 50%
wide and not exceed 75ch
:
p {
width: min(75ch, 50%);
}
Or, if you want the element to be at least 45ch
:
p {
width: max(45ch, 50%);
}
Enable an element to have additional padding at larger screen sizes, while maintaining a minimum padding at smaller screen sizes.
footer {
padding: var(--blockPadding) max(2rem, 50vw - var(--contentWidth) / 2);
}
.element {
padding: 1.5rem clamp(1rem, 5%, 3rem);
}
clamp()
is great for accomplishing fluid typography. You can set a minimum, ideal and maximum size that scales with the viewport width:
p {
font-size: clamp(1.5rem, 5vw, 3rem);
- minimum: 1.5rem
- ideal: 5vw
- max: 3rem
}
.colors {
--base-hue: 140;
--saturation: 95%;
--lightness: 80%;
--rotation: 60;
color: #222;
text-align: center;
}
.color {
padding: 0.25rem;
background-color: hsl(var(--hue), var(--saturation), var(--lightness));
}
.color1 {
--hue: calc(var(--base-hue));
}
.color2 {
--hue: calc(var(--base-hue) + var(--rotation));
}
.color3 {
--hue: calc(var(--base-hue) + var(--rotation) * 2);
}
- Tall viewports (phones/tablets):
8vh
is used - Short viewports (monitors):
2rem
is used
.element + .element {
margin-top: max(8vh, 2rem);
}
url()
set background-image, list-style, cursor, border, etc.var()
insert the value of a CSS variable.
Transform Functions
translate(x, y)
*scale()
*rotate()
*perspective()
Stepped Value Functions
round()
roundingmod()
modulus
Exponential Functions
pow(a,b)
a to the power of bsqrt(a)
square root of a
Sign-related Functions
abs()
absolute valuesign()
returns -1 (negative #), 1 (positive #)
Filter Functions
Applies graphical effect on anCounter Functions
drop-shadow()
grayscale()
hue-rotate()
invert()
opacity()
saturate()
sepia()
Color Functions
rgb()
rgba()
hsl()
hsla()
Image Functions
May be used wherever an <image>
is valid as a value for a property:
content
for pseudo-elementbackground-image
list-style-image
border-image-source
cursor
Functions:
conic-gradient()
* circular gradientlinear-gradient()
* linear gradientcross-fade()
Counter Functions
counter()
Shape Functions
May be used as values for the <basic-shape>
data type, which is used by clip-path
, offset-path
and shape-outside
properties.
circle()
ellipse()
inset()
polygon()
path()
Reference Functions
attr()
env()
url()
var()
CSS Grid Functions
fit-content()
min-max()
repeat()
CSS Variables (aka Custom CSS Properties) are useful & powerful tools when writing our CSS files. They allow us to reference a value several times throughout a file and allow us to change all of those values in a single place.
.error-modal {
--color-error-text: red;
--modal-border: 1px solid black;
--modal-font-size: calc(2rem + 5vw);
color: var(--color-error-text);
border: var(--modal-border);
font-size: var(--modal-font-size);
}
var()
accepts two parameters: a CSS custom property and an optional fallback value. The fallback value is used if the custom property is invalid or hasn't been declared yet.
.fallback {
--color-text: white;
background-color: var(--undeclared-property, black);
color: var(--undeclared-again, var(--color-text, yellow));
}
The scope of custom properties is determined by the selector. This scope includes the selector the custom property lives in, as well as any descendant.
Declaring custom properties in the :root
selector is essentially the same as the html
selector, but it has a higher specificity. It allows us to declare global variables that can be used throughout our projects.
:root {
--color-black: #000;
}
.div-container {
background: var(--color-black);
}
The :root
selector allows us one way to add themes to our pages.
- Add
class
attribute on ourhtml
element (javascript) - Add 2 scopes for the CSS custom properties, using the
.dark
and.light
classes, which contain different values for the same custom CSS properties.
<div class="container">
<p>
You're now viewing this example with the
<span class="theme-name">dark</span> theme!
</p>
<button class="theme-toggle">Toggle Theme</button>
</div>
:root.dark {
--border-btn: 1px solid rgb(220, 220, 220);
--color-base-bg: rgb(18, 18, 18);
--color-base-text: rgb(240, 240, 240);
--color-btn-bg: rgb(36, 36, 36);
}
:root.light {
--border-btn: 1px solid rgb(36, 36, 36);
--color-base-bg: rgb(240, 240, 240);
--color-base-text: rgb(18, 18, 18);
--color-btn-bg: rgb(220, 220, 220);
}
body,
.theme-toggle {
color: var(--color-base-text);
}
body {
background-color: var(--color-base-bg);
padding: 10px;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
}
p {
font-size: 1.5rem;
}
.theme-toggle {
background-color: var(--color-btn-bg);
border: var(--border-btn);
font-size: 1.125rem;
padding: 10px 20px;
}
.theme-toggle:hover {
cursor: pointer;
}
.theme-toggle:focus {
outline: var(--border-btn);
}
function setTheme() {
const root = document.documentElement;
const newTheme = root.className === "dark" ? "light" : "dark";
root.className = newTheme;
document.querySelector(".theme-name").textContent = newTheme;
}
document.querySelector(".theme-toggle").addEventListener("click", setTheme);
Media Queries allow us to theme our applications based on the user's operating system or user agent (like a browser)'s preference. This is accomplished with the prefers-color-scheme
media query, which checks if a user has selected a theme preference in their OS/user agent.
- Possible values:
light
ordark
:root {
--border-btn: 1px solid rgb(36, 36, 36);
--color-base-bg: rgb(240, 240, 240);
--color-base-text: rgb(18, 18, 18);
--color-btn-bg: rgb(220, 220, 220);
--theme-name: "light";
}
@media (prefers-color-scheme: dark) {
:root {
--border-btn: 1px solid rgb(220, 220, 220);
--color-base-bg: rgb(18, 18, 18);
--color-base-text: rgb(240, 240, 240);
--color-btn-bg: rgb(36, 36, 36);
--theme-name: "dark";
}
}
body {
background-color: var(--color-base-bg);
color: var(--color-base-text);
padding: 10px;
}
Default: Light (no preference or browser doesn't support the media query)
If dark
is the value of prefers-color-scheme
, the media-query overwrites the default custom properties of :root
.
To use the values of custom properties in JavaScript:
// get variable from inline style
element.style.getPropertyValue("--my-var");
// get variable from whever
getComputedStyle(element).getPropertyValue("--my-var");
// set variable on inline style
element.style.setProperty("--my-var", jsVar + 4);
Browser History:
- 1995 Internet Explorer
- Netscape launched Mozilla > Firefox
- 2003 Apple Safari
- 2008 Google Chrome
Chrome & Chromium-based browsers are the dominant player.
A shift has occurred, from standalone applications to HTML5 and Progressive Web Apps, that allow applications to fully function within a web browser.
- Apps like Microsoft Word & Excel can now be utilized through any web browser, without the need of a standalone application.
Different browsers use different engines to display info on a page:
- Chrome/Chromium: Blink
- Safari: WebKit
Your applications may behave differently depending on what browser you're using.
- Vast majority of apps are designed to work smoothly with Chromium, and providing as good performance in other browsers is secondary.
For web development projects to have a broader reach, you must make sure you're testing your web apps against the browsers which are most likely to be used
- Chrome
- Safari
- Firefox
- Chromium: Edge, Brave, etc.
You also may need to support less common ones: IE.
W3C World Wide Web Consortium is the authority behind developing web standards
- Maximize accessibility
- Consistency of the web experience
- Develop new CSS features
Risk is involved when rushing to use new features.
To help prevent compatibility issues, "Can I Use" is a great tool for the job.
Implementing new features should wait until they are supposed by the most common browsers.
In some areas of the world, mobile users are a vast majority.
- Tablets
- Smartphones
Most popular mobile operating systems:
- Android
- Apple iOS
You must consider whether your application should be fully mobile compatible:
iOS & iPadOS
- Safari is technically the only supported browser.
- On iOS, Chrome/Firefox are not full browsers.
- They use Safari rendering engine (WebKit).
For your web app to work for Apple users, you have to support WebKit & other technologies used in Safari.
Mobile browers != Desktop browsers. Adjustments may be needed to work properly on the mobile version of the same browser.
Different Screen Sizes
It's impossible to test every possible physical device. Browsers can emulate other devices, but only their screen sizes.
- UI address bar, bookmark, back/forward
- Browser Engine marshals actions between UI/rendering engine.
- Rendering Engine displays request content. ie: html > parses html/css & displays it on screen
- html, xml, images, others via plugins: pdf
- Networking calls, HTTP requests
- UI Backend drawing widgets, combo boxes, windows. Exposes a generic interface that is not platform specific. Underneath it uses the operating system user interface methods.
- JavaScript Interpreter parse & execute JS code
- Data Storage persistence layer, saves data locally, cookies. ie: localStorage, IndexedDB, WebSQL, FileSystem
Chrome runs multiple instances of the rendering engine: 1 per tab.
Rendering Engines
- Internet Explorer: Trident
- Firefox: Gecko
- Safari: WebKit
- Chrome: Blink (fork of WebKit)
WebKit is an open source rendering engine. Began as an engine for Linux & was modified by Apple to support Mac/Windows.
CSS Frameworks & Preprocessors can make writing CSS more streamlined and less tedious.
They are important because they are commonly found in the workplace. Many job requirements include Bootstrap, SASS, and related technology.
Bootstrap, Tailwind, Bulma & Foundation
- Bundle CSS you can use/access via classes defined by the framework
- Do a lot of the heavy lifting of packaging up commonly used CSS code
- Icons
- Interactions (dropdown menus)
Example:
.btn
adds all the needed styles to your buttons
In order to use a framework, you need to understand:
- how it expects you to lay out your site.
- which classes it uses to designate its particular batch of styles
Advantages
- Gives teams ready made documentation
- Online communities: Easy access to help
- Grid system
- Speed of project delivery
- "I'm not a designer!"
- Dealing with CSS bugs & Browser compatibility
- Help with Responsive design
Disadvantages:
- All websites end up looking the same
- New developers jump into learning frames too early in their education
- Never learn vanilla CSS
- Don't get enough practice to solidify the fundamentals
- Overriding a framework's styling or debugging style issues is difficult if you haven't mastered CSS fundamentals
- Need to know what's happening under the hood
Preprocessors (aka precompilers) are languages that help you write CSS more easily.
- Reduce repetition
- Provide time-saving & code-saving features
- Write Loops
- Join multiple stylesheets
- Nest classes
Preprocessors are extensions to vanilla CSS that provide extra functionality:
- Nesting
- Mixins
- Variables
When you run the processor, it takes your code and turns it into vanilla CSS that you can import into your project.
Disadvantages
- Debugging is harder
- Compilation slows down development
- Can produce very large CSS files
- Maintenance & Over-engineering
- Tooling & Developer Convenience
- Saving generated files
Grid was inspired by other forms of media: newspapers and magazines.
Flexbox allows us to position and align items on one of two axis: main & cross. It also allows us to grow, shrink and change the size of flex items. flex-wrap
allows us to take flex items and move them to the next line. However, this isn't always easy and it's not the best tool for the job.
In other words, Flexbox is best used on a single dimension: up/down.
Grid makes creating two-dimensional layout much easier. Grid can also create one-dimensional layouts, giving developers the option of adding a second row later on.
Grid shares many similarities with Flexbox:
- Parent containers
- Child items
- Similar property names (alignment/positioning)
While Flexbox can struggle to make all child items match evenly in size, Grid makes this much easier.
- Flexbox Layout: mostly defined in child items
- Grid Layout: mostly defined in parent element
Grid is better at overlapping
- Place items on overlapping grid lines, or within the same exact grid cells.
Grid is sturdier
- Grid has space-occupying features: fractional units, content can break grids
- Flexbox sizing is complicated:
width
min-width
flex-basis
flex-grow
flex-shrink
Quotes:
- "Flexbox is for alignment. Grid is for layout."
- "If you start giving flex items a width, grid will be easier to use."
- "Grid is best suited for 2D & overlapping elements, while flexbox shines in simpler/common layout requirements."
Grid Containers will contain the whole grid. This is accomplished with:
/* block level */
display: grid;
/* inline level */
display: inline-grid;
- Grid containers only affect their direct children.
- Grid items can also be grid containers.
Specifying grid columns and rows defines the grid track or the space between lines on a grid. This is done with the grid-template-columns
and grid-template-rows
properties.
.container {
display: grid;
grid-template-columns: 50px 50px;
grid-template-rows: 50px 50px;
}
grid-template
is a shorthand property for both grid-template-columns
and grid-template-rows
.
.container {
display: grid;
grid-template: 50px 50px / 50px 50px;
/* equivalent to:
grid-template-columns: 50px 50px;
grid-template-rows: 50px 50px; */
}
Adding a 5th div to a 2x2 grid will land in a third row that isn't explicitly defined.
The implicit grid concept is how CSS automatically places grid items, even when we haven't explicitly defined a layout for them.
- Size values established by our
grid-template-columns
grid-template-rows
are NOT carried over into these implicit grid tracks.
Implicit guide track sizes are created using the grid-auto-rows
and grid-auto-columns
properties.
If we want any new rows to stay the same value as our explicit row track sizes:
.container {
display: grid;
/* explicit guide tracks */
grid-template-columns: 50px 50px;
grid-template-rows: 50px 50px;
/* implicit guide tracks */
grid-auto-rows: 50px;
}
Much less common option: Add extra content horizontally (row) w/ grid-auto-flow: column
property. Implicit track sizes are set w/ the grid-auto-columns
property.
Gaps between rows/columns are known as gutters / alleys.
There are column-gap
and row-gap
properties to control which axis receives a gap.
gap
is shorthand for column-gap
and row-gap
.
- Grid track: entire row or column of a the grid.
- Defined exlicitly
- Grid line: dividing line that makes up the grid structure.
- Created implicitly - after our tracks are defined.
- Grid cell: space between row/column grid lines.
- Smallest unit of measurement in grid.
- Default size of each child element
- Grid area: any space surrounded by 4 grid lines
- ie: 2x1 group of cells, 2x6 group of cells
To get grid badges in devtools, click on (grid)
in the DOM tree. The layout
tab also have useful settings for grid.
To test grid alignment properties:
The following properties allow us to position grid items based on column grid and column row lines. This allows them to span across multiple lines.
/* Grid ITEM Level */
grid-column: 1 / 6; /* grid-column: start / end */
grid-column-start: 1;
grid-column-end: 6;
grid-row: 1 / 3; /* grid-row: start / end; */
grid-row-start: 1;
grid-row-end: 3;
Defaults: If an item spans one track (column/row), you can omit grid-column-end
/grid-column-row
.
Grid Area is another shorthand available, which includes all 4 positioning properties:
grid-area:
grid-row-start /
grid-column-start /
grid-row-end /
grid-column-end;
#living-room {
grid-area: 1 / 1 / 3 / 6;
}
However, this can get confusing. Instead of using grid lines, we can create a visual layout of the grid in words. To do this, we give each item on the grid a name using grid-area
:
#living-room {
grid-area: living-room;
}
This is possible for all grid items. We can then map out the whole structure with the grid container, using grid-template-areas
.
.container {
display: inline-grid;
grid-template: 40px 40px 40px 40px 40px / 40px 40px 40px 40px 40px;
background-color: lightblue;
grid-template-areas:
"living-room living-room living-room living-room living-room"
"living-room living-room living-room living-room living-room"
"bedroom bedroom bathroom kitchen kitchen"
"bedroom bedroom bathroom kitchen kitchen"
"closet closet bathroom kitchen kitchen";
}
.
can be used to indicate an empty cell.
Negative grid lines can be used to go from right to left.
Instead of specifying a grid start/end lines by number, you can specify a start line and then the number of tracks you'd like the area to span.
.box2 {
grid-column: 3;
grid-row: 1 / span 2;
}
Verically aligning items on the block axis: align-self
, align-items
.
Horizontally justifying items on the inline axis: justify-self
justify-items
- auto
- normal
- start
- end
- center
- stretch
- baseline
- first baseline
- last baseline
margin-left/right: auto
repeat()
is a css function that allows us to define multiple values without repeating it over and over.
.grid-container {
grid-template-rows: repeat(2, 150px);
grid-template-columns: repeat(5, 150px);
}
fr
is a grid specific unit of measurement that allows us to start making them dynamic or flexible.
fr
represents a fraction of the available space in a container.
2fr
would be twice as large as1fr
min-content
is the smallest size an element can be without overflowing.
- in a
<p>
,min-content
would be the size of the largest word within it.
Using CSS functions min()
and max()
are useful in declaring track sizes in responsive designs:
.grid-container {
grid-template-rows: repeat(2, min(200px, 50%));
grid-template-columns: repeat(5, max(120px, 15%));
}
minmax()
is a grid-only CSS function. It can be used with:
grid-template-columns
grid-template-rows
grid-auto-columns
grid-auto-rows
minmax()
accepts two values: minimum track size & maximum track size.
Unlike min()/max()
, it can make sense to use 2 static values for both arguments.
.grid-container {
grid-template-rows: repeat(2, 1fr);
grid-template-columns: repeat(5, minmax(150px, 200px));
}
Dynamic sizing occurs when grid container changes size.
clamp(minimum-size, ideal-size, maximum-size)
Since clamp's purpose is to create flexibly-size track with constraints, we want to use:
- Ideal value: Dyanmic measurement
- Min/Max: Static measurement
.simple-example {
width: clamp(500px, 80%, 1000px);
}
auto-fill
& auto-fit
functions return “the largest possible positive integer” without the grid items overflowing their container
The real magic of auto-fill
and auto-fit
is when we use minmax()
as well.
With minmax()
, we tell grid that we want as many columns as possible, while limiting each column's size without overflowing our grid.
.grid-container {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
In the above example:
autofit()
returns highest possible integer without overflowing- It needs grid width. default: window width, minus margins. (ie:
500px
) - Browser determines how many grid column tracks could fit in that width.
- Using
minmax()
, it takes the minimum value150px
to find out.- Grid will render 3x
150px
columns in the grid (3x150px
=450px
)
- Grid will render 3x
- Browser then resizes those 3x columns to fit the maximum allowed value of
minmax()
--1fr
auto-fill
works the exact same way as auto-fit
, except when there are not enough items to fill up an entire grid row once.
auto-fit
keeps grid items at theirMAX
size.auto-fill
keeps grid items at theirMIN
size.
If your design originates with the content first, Flexbox is a good choice when starting with the smallest parts outwards.
If given a specific overall layout to adhere to (explicit placement of elements in two dimensions).
Ultimately, it's PERSONAL PREFERENCE.
Transforms:
- change appearance of elements
- don't affect natural document flow
Basics:
- Takes 1+ CSS transform functions as values
- Each ^ function takes own value: angle or number
- All elements can have transform, except for:
<col>
<colgroup>
<span>
,<b>
,<em>
(non-replaced inline elements)
.element {
transform: rotate();
}
/* examples */
.rotate-by-deg {
transform: rotate(45deg);
}
.rotate-by-rad {
transform: rotate(-1rad);
}
.rotate-by-turn {
transform: rotate(0.3turn);
}
.element {
transform: scaleX();
transform: scaleY();
transform: scale();
}
/* examples */
.scaleX {
transform: scaleX(0.25);
}
.scaleY {
transform: scaleY(1.5);
}
.scaleXY {
transform: scale(0.25, 1.5);
}
.scale {
transform: scale(0.5);
}
Skew: | |
to \ \
.element {
transform: skewX();
transform: skewY();
transform: skew();
}
/* examples */
.skewX {
transform: skewX(45deg);
}
.skewY {
transform: skewY(-0.5rad);
}
.skewXY {
transform: skew(45deg, -0.5rad);
}
.skew {
/* single value behaves the same as skewX */
transform: skew(45deg);
}
.element {
transform: translateX();
transform: translateY();
transform: translate();
}
/* examples */
.translateX {
transform: translateX(20px);
}
.translateY {
/* percent values are of the element's width */
transform: translateY(-33%);
}
.translateXY {
transform: translate(20px, -33%);
}
Transforms are executed from left > right.
<div class="red-box"></div>
<div class="blue-box"></div>
.red-box,
.blue-box {
position: absolute;
width: 100px;
height: 100px;
}
.red-box {
background: red;
transform: rotate(45deg) translate(200%);
}
.blue-box {
background: blue;
transform: translate(200%) rotate(45deg);
}
perspective
is required to work on a 3d plane:
rotate
,scale
andtranslate
work on a 3d plane as well.
Setting a perspective value: object should render as if we're viewing it from a specific distance on the z-axis.
- Perspective must be declared 1st w/ multiple transform functions
.element {
transform: perspective();
}
Perspective Rotate:
.element {
transform: rotateX();
transform: rotateY();
transform: rotateZ();
transform: rotate3d();
}
/* examples */
.rotateX {
transform: rotateX(60deg);
}
.rotateY {
transform: rotateY(60deg);
}
.rotateZ {
transform: rotateZ(60deg);
}
.rotate3d {
transform: rotate3d(x, y, z, a);
}
Perspective Scale:
.element {
transform: scaleZ();
transform: scale3d();
}
Perspective Translate:
.element {
transform: translateZ();
transform: translate3d();
}
translateZ()
& perspective
: create illusion of 3d distance
Matrix (uncommonly used):
- Combines all transform functions into one
Most devices: 60fps
- Screens refresh 60 times a second
- Animations/transitions/scrolling: browser needs to match ^ refresh rate
- Each frame: budget of 16ms (1 second / 60)
- Brower has maintenance to do: work needs to finish in 10ms
If you fail to meet the budget, frame rate drops & content judders.
- ie: jank
Pixel Pipeline: 5 areas where you have the most control
- JavaScript / CSS animations/transitions / Web Animations API
- Style calculations: each element > which rules to apply where & then applied
- Layout: calculates how much space is taken up & where on screen, how elements affect one another
- Paint: filling in pixels, drawing text, colors, images, borders, etc. on layers
- Composite: when multiple layers are drawn ^, they need to be drawn in the correct order. (overlapping)
The type of changes made affect the pixel pipeline:
- Layout: element geometry, height, width, etc.
- browser has to check all other elements
- JS > Style > Layout > Paint > Composite
- Paint only: background image, text color, shadows
- browser skips Layout step
- JS > Style > Paint > Composite
- Animations/scrolling
- Skips layout & paint
- JS > Style > Composite
Because of the Pixel Pipeline, transform property is great.
- It occurs during composition
- Can be hardware-accelerated (device's GPU)
- Translate
- move item around
- close button outside of modal
- Scale
- grow or shrink an element
- old time tv:
transform: scale(0.5, 0);
(shrinks width 50%, height 100%)
- Rotate
- rotate elements
0.2turn
for percentages (of 360 degrees)
- Skew (seldomly used)
Transitions: change an element's initial & end state.
- Hover effects
transition
is a shorthand property for:
transition-property
- what css property will be transitioned
transition-duration
- how long it takes
transition-timing-function
- speed of transition
transition-delay
- delay before transition starts
div {
transition: <property> <duration> <timing-function> <delay>;
}
/* example */
button {
/* ... other CSS properties ... */
background-color: white;
transition: background-color 1s ease-out 0.25s;
}
button:hover {
background-color: black;
}
Performance: Generally not an issue. There are a few gotchas:
div {
width: 100px;
height: 100px;
transition: transform 2s 1s;
}
div:hover {
transform: rotate(180deg);
}
- Stacking contexts causes nested elements to repaint every time the parent does.
- Restrict animations to opacity & transform (for performance reasons)
- Things like background-color are expensive operations
const f = document.getElementById("foo");
document.addEventListener(
"click",
(ev) => {
f.style.transform = `translateY(${ev.clientY - 25}px)`;
f.style.transform += `translateX(${ev.clientX - 25}px)`;
},
false,
);
.ball {
border-radius: 25px;
width: 50px;
height: 50px;
background: #c00;
position: absolute;
top: 0;
left: 0;
transition: transform 1s;
}
el.addEventListener("transitionend", updateTransition, true);
// before any delay
el.addEventListener("transitionrun", signalStart, true);
// after any delay
el.addEventListener("transitionstart", signalStart, true);
- What exactly am I animating?
- Could it be "layers"?
- "Layer borders" in Edge DevTools
- What about "stacking context"?
- "3D View" panel in Edge DevTools
- Root
<html>
z-index
other thanauto
ANDposition: relative/absolute
flex
child w/z-index
grid
child w/z-index
position: fixed/sticky
opacity
other than1
mix-blend-mode
other than normaltransform
filter
backdrop-filter
perspective
clip-path
mask / mask-image / mask-border
isolation
will-change
contain
value layout, paint, composite:contain: strict
contain: content
-
Transitions: animate element, one state, to another
- Can loop, but weren't meant to
- Animations: were designed to explicitly enable loop
-
Transitions: need a trigger: hover, focus, toggling classes
- Animations: do NOT need a trigger
-
Transitions: not as flexible as animations
- Transitions: straight line, point a to point b
#ball {
/* ... other CSS properties ... */
animation-duration: 2s;
animation-name: change-color; /* @keyframes */
animation-iteration-count: infinite;
animation-direction: alternate;
}
@keyframes change-color {
from {
background-color: red;
}
to {
background-color: green;
}
}
Keyframes at-rule (single cycle - not a complete loop)
- from: alias for 0% (at zero seconds)
- to: alias for 100% (at 2 seconds/animation-duration value)
Shorthand Notation:
#ball {
/* ... other CSS properties ... */
background-color: red;
animation: 2s change-color infinite alternate;
}
@keyframes change-color {
from {
background-color: red;
}
50% {
width: 200px;
height: 200px;
background-color: blue;
}
to {
background-color: green;
}
}
- 50% (percentage of animation-duration)
- 50% of 1s duration: 0.5s
- Only
0/100%
can usefrom/to
aliases
div {
/* unique durations/iteration counts */
animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 2.5s, 5s, 1s;
animation-iteration-count: 2, 1, 5;
/* all 3 animations share duration/count */
animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 3s;
animation-iteration-count: 1;
}
- Back & forth:
animation-direction: alternate;
- Loops:
animation-iteration-count: infinite
Animate drop down menu:
.container {
/* offscreen, above viewport */
transform: translate(-50%, -75vh);
/* first moves the container in position, then fades out after */
transition: transform 0.5s ease-in-out, opacity 0.5s ease;
}
.container