CSS
Reset
This CSS article provides some background on resets.
Most popular, undoes default user agent styles.
Tweaks styles to make them consistent.
Look up elements and see default user agent styles, support, etc.
User agent styles
Example
Add this reset to your file (adapted from A Modern CSS Reset):
NOTE CSS In-depth recommended adding this to each stylesheet:
button, input { font: inherit; }
This might be taken care of by the
* {... font: inherit; }
ruleset below.
/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Remove default margin */
* {
margin: 0;
padding: 0;
/* inherit font so you can define styles
for h1, h* elements instead of rely on user
agent defaults */
font: inherit;
}
/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
ul[role="list"],
ol[role="list"] {
list-style: none;
}
/* Set core root defaults */
html:focus-within {
scroll-behavior: smooth;
}
html,
body {
height: 100%;
}
/* Set core body defaults */
body {
text-rendering: optimizeSpeed;
line-height: 1.2;
}
/* A elements that don't have a class get default styles */
a:not([class]) {
text-decoration-skip-ink: auto;
}
/* Make images easier to work with */
img,
picture,
svg {
max-width: 100%;
display: block;
}
/* Remove all animations, transitions and smooth scroll for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
/* button, */
input,
select,
textarea {
width: 150px;
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: inherit;
font-size: 100%;
/* removes system-level styling */
appearance: none;
}
Set up variables
This example shows you how to set up variables for the entire site:
:root {
--clr-accent-500: hsl(12, 60%, 45%);
--clr-accent-400: hsl(12, 88%, 59%);
--clr-accent-300: hsl(12, 88%, 75%);
--clr-accent-100: hsl(13, 100%, 96%);
--clr-primary-400: hsl(228, 39%, 23%);
--clr-neutral-900: hsl(232, 12%, 13%);
--clr-neutral-100: hsl(0 0% 100%);
--ff-primary: "Be Vietnam Pro", sans-serif;
--ff-body: var(--ff-primary);
--ff-heading: var(--ff-primary);
--fw-regular: 400;
--fw-semi-bold: 500;
--fw-bold: 700;
--fs-300: 0.8125rem;
--fs-400: 0.875rem;
--fs-500: 0.9375rem;
--fs-600: 1rem;
--fs-700: 1.875rem;
--fs-800: 2.5rem;
--fs-900: 3.5rem;
--fs-body: var(--fs-400);
--fs-primary-heading: var(--fs-800);
--fs-secondary-heading: var(--fs-700);
--fs-nav: var(--fs-500);
--fs-button: var(--fs-300);
--size-100: 0.25rem;
--size-200: 0.5rem;
--size-300: 0.75rem;
--size-400: 1rem;
--size-500: 1.5rem;
--size-600: 2rem;
--size-700: 3rem;
--size-800: 4rem;
--size-900: 5rem;
}
@media (min-width: 50em) {
:root {
--fs-body: var(--fs-500);
--fs-primary-heading: var(--fs-900);
--fs-secondary-heading: var(--fs-800);
--fs-nav: var(--fs-300);
}
}
Forms
<body>
<h1>Registration Form</h1>
<p>Please fill out this form with the required information</p>
<form action="https://register-demo.freecodecamp.org" method="post">
<fieldset>
<label for="first-name"
>Enter Your First Name:
<input id="first-name" type="text" name="first-name" required
/></label>
<label for="last-name"
>Enter Your Last Name:
<input id="last-name" type="text" name="last-name" required
/></label>
<label for="email"
>Enter Your Email: <input id="email" type="email" name="email" required
/></label>
<label for="new-password"
>Create a New Password:
<input
id="new-password"
type="password"
pattern="[a-z0-5]{8,}"
name="new-password"
required
/></label>
</fieldset>
<fieldset>
<label for="personal-account"
><input
class="inline"
id="personal-account"
type="radio"
name="account-type"
/>
Personal Account</label
>
<label for="business-account"
><input
class="inline"
id="business-account"
type="radio"
name="account-type"
/>
Business Account</label
>
<label for="terms-and-conditions">
<input
class="inline"
id="terms-and-conditions"
type="checkbox"
name="terms-and-conditions"
required
/>
I accept the
<a href="https://www.freecodecamp.org/news/terms-of-service/"
>terms and conditions</a
>
</label>
</fieldset>
<fieldset>
<label for="profile-picture"
>Upload a profile picture:
<input id="profile-picture" type="file" name="profile-picture"
/></label>
<label for="age"
>Input your age (years):
<input id="age" type="number" min="13" max="120" name="age"
/></label>
<label for="referrer"
>How did you hear about us?
<select id="referrer" name="referrer">
<option value="">(select one)</option>
<option value="1">freeCodeCamp News</option>
<option value="2">freeCodeCamp YouTube Channel</option>
<option value="3">freeCodeCamp Forum</option>
<option value="4">Other</option>
</select>
</label>
<label for="bio"
>Provide a bio:
<textarea
id="bio"
rows="3"
cols="30"
name="bio"
placeholder="I like coding on the beach..."
></textarea>
</label>
</fieldset>
<!-- The first input element with a type of submit is automatically set to submit its nearest parent form element. -->
<input type="submit" value="Submit" />
</form>
</body>
The related CSS stylesheet:
body {
width: 100%;
height: 100vh;
margin: 0;
background-color: #1b1b32;
color: #f5f6f7;
font-family: Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
}
label {
display: block;
margin: 0.5rem 0;
}
h1,
p {
margin: 1em auto;
text-align: center;
}
form {
margin: 0 auto;
max-width: 500px;
min-width: 300px;
width: 60vw;
padding: 0 0 2em 0;
}
fieldset {
border: none;
padding: 2rem 0;
border-bottom: 3px solid #3b3b4f;
}
fieldset:last-of-type {
border-bottom: none;
}
/*
fieldset:not(:last-of-type) {
border-bottom: 3px solid #3b3b4f;
} */
input,
textarea,
select {
width: 100%;
margin: 10px 0 0 0;
min-height: 2em;
}
.inline {
/* unsets the 100% width */
width: unset;
margin: 0 0.5em 0 0;
vertical-align: middle;
}
input,
textarea {
background-color: #0a0a23;
border: 1px solid #0a0a23;
color: #fff;
}
input[type="submit"] {
display: block;
width: 60%;
margin: 1em auto;
height: 2em;
min-width: 300px;
font-size: 1.1rem;
background-color: #3b3b4f;
border-color: white;
}
input[type="file"] {
padding: 1px 2px;
}
a {
color: #dfdfe2;
}
HTML elements reference CSS Cheat sheet
Emmet
Official docs Emmet cheat sheet Keybindings plugin
Find key bindings with Ctrl + k then Ctrl + s.
Wrapper
.wrapper>h1{Title}+.content
<div class="wrapper">
<h1>Title</h1>
<div class="content"></div>
</div>
Auto-gen
Creates button:
button[type="button"]
Creates div
[data-selected]
Add text to auto-gen elements:
header>nav>ul>li*3{test}
<header>
<nav>
<ul>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>
</nav>
</header>
Dynamic auto-gen:
header>nav>ul>li*3{List Item $}
<header>
<nav>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</nav>
</header>
Dynamic classes:
header>nav>ul>li*3.class-${List Item $}
<header>
<nav>
<ul>
<li class="class-1">List Item 1</li>
<li class="class-2">List Item 2</li>
<li class="class-3">List Item 3</li>
</ul>
</nav>
</header>
Zero padding
header>nav>ul>li*3.class-${List Item $$}
<header>
<nav>
<ul>
<li class="class-1">List Item 01</li>
<li class="class-2">List Item 02</li>
<li class="class-3">List Item 03</li>
</ul>
</nav>
</header>
Grouping
Group with parentheses:
(header>nav)+main+footer
<header>
<nav></nav>
</header>
<main></main>
<footer></footer>
Complex example:
(header>h2{Heading}+nav>li*5>a{Link $})+main+footer
<header>
<h2>Heading</h2>
<nav>
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li><a href="">Link 4</a></li>
<li><a href="">Link 5</a></li>
</nav>
</header>
<main></main>
<footer></footer>
Forms
form:post>.group>input:text
<form action="" method="post">
<div class="group"><input type="text" name="" id="" /></div>
</form>
form:post>(.group>label+input:text)+(.group>label+input:number)
<form action="" method="post">
<div class="group">
<label for=""></label><input type="text" name="" id="" />
</div>
<div class="group">
<label for=""></label><input type="number" name="" id="" />
</div>
</form>
SVG (Scalable Vector Graphics)
SVGs scale to any size without losing quality or increasing file size, and you can modify them with CSS or JS.
Play around with it here: SvgPathEditor.
Links
Free libraries
Misc
Use cases
- Icons
- Graphs/Charts
- Large, simple images
- Patterned backgrounds
- Applying effects to other elements via SVG filters
Anti-use cases
Inefficient for storing complex images.
Anatomy
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect x="0" y="0" width="100" height="100" fill="burlywood" />
<path
d="M 10 10 H 90 V 90 L 10 60"
fill="transparent"
stroke="black"
stroke-width="3"
/>
<circle cx="50" cy="50" r="20" class="svg-circle" />
<g class="svg-text-group">
<text x="20" y="25" rotate="10" id="hello-text">Hello!</text>
<use href="#hello-text" x="-10" y="65" fill="white" />
</g>
</svg>
xmlns
: XML namespace. Specifies the XML dialect that you are using so the browser can render the SVG correctly.viewBox
: Defines the bounds of the SVG—the positions of different points of the SVG elements in the following order:min-x
,min-y
,width
, andheight
Also defines the aspect ratio (ratio of width to height) and the origin (the image’s origin of motion for an animation).
class
,id
: Same funciton as in CSS or JS.<circle>
,<rect>
,<path>
,<text>
, other elements: Defined by the SVG namespace that let you build SVGs.CSS tricks SVG Elements by Category
fill
andstroke
: Properties that you can edit with CSS and JS.
Embedding SVGs
- Link with an
<img>
tag or withbackground-image: url(./path/to/.svg);
- You cannot edit these SVGs.
- Embed it in the HTML file.
- Makes HTML harder to read
- Page is less cacheable
- Slows HTML loading
You can minimize these drawbacks with React or Webpack.
Tables
CSS properties
background
Includes 8 properties that can do the following:
- change background color
- add background images
- change position and size of background images
- repeat or tile the images
- create background layers
box-shadow
Adds effects around elements.
overflow
How an elment behaves when its content is too big.
opacity
Sets the opacity.
Advanced selectors
Pseudo-classes
MDN classes vs elements MDN docs
Classes use a single colon and target elements that already exist in the HTML. Some common ones are:
:focus
:hover
:active
Structural pseudo-classes:
:root
that represents the very top level of your document:first-child
:last-child
:empty
for elements that have no children at all:only-child
for elements that do not have any siblings:nth-child
.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 */ }
Pseudo-elements
Elements use a double colon and target elements that do not normally exist or are not elements at all:
::marker
styleli
bullets or numbers::first-letter
::first-line
::selection
change styling when user selects text on the page.::before
::after
Advanced selectors
Complete list MDN attribute selectors Complex Selectors CSS Tricks: Taming Advanced CSS Selectors CSS Tricks: The Skinny on CSS Attribute Selectors
Select and style any attribute:
[attribute]
selector[attribute]
[attribute="value"]
[src] {
/* This will target any element that has a src attribute. */
}
img[src] {
/* This will only target img elements that have a src attribute. */
}
img[src="puppy.jpg"] {
/* This will target img elements with a src attribute that is exactly "puppy.jpg" */
}
[attribute^="value]
match from the start[attribute$="value"]
match from the end[attribute*="value]
match anywhere inside the string
[class^="aus"] {
/* Classes are attributes too!
This will target any class that begins with 'aus':
class='austria'
class='australia'
*/
}
[src$=".jpg"] {
/* This will target any src attribute that ends in '.jpg':
src='puppy.jpg'
src='kitten.jpg'
*/
}
[for*="ill"] {
/* This will target any for attribute that has 'ill' anywhere inside it:
for="bill"
for="jill"
for="silly"
for="ill"
*/
}
CSS Functions
Practical use cases MDN complete list of functions min(), max(), clamp() info
calc()
You can nest calc()
:
:root {
--header: 3rem;
--footer: 40px;
--main: calc(100vh - calc(var(--header) + var(--footer))); /*
--main: calc(100vh - (3rem + 40px))
*/
}
min()
Applies the smaller value to the element:
img {
width: min(150px, 100%);
}
If there is 150px available to the image, then it uses it. Otherwise, the image is set to 100% of its parent element.
You can also see this as “at maximum, the image is 150px wide”
max()
Applies the larger value to the element:
img {
width: min(100px, 4em, 50%);
}
If there is enough viewport size to apply 4em or 50%, then it is applied. If there isn’t, the image is 100px wide.
clamp()
Makes elements fluid and responsive. Accepts 3 values:
- smallest val
- ideal val
- largest val
h1 {
font-size: clamp(320px, 80vw, 60rem); /*
font-size: clamp(smallest, ideal, largest); */
}
Custom properties
CSS variables that you can use within the context or scope that they are defined.
Fallback values
.fallback {
--color-text: white;
background-color: var(--undeclared-property, black);
color: var(--undeclared-again, var(--color-text, yellow));
}
Scope
The scope of a custom property includes the selector that the custom property was delcared in, and any descendants of that selector.
To make custom properties globally available, put them on the :root
selector:
:root {
--custom-prop: value;
}
Themes with custom properties
You can add dark and light themes with custom properties. First, create the theme colors with class styles on the :root
element:
: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);
}
/* apply custom props to elements below */
Then, use JS to grab the root element (documentElement
), and toggle the theme:
let 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);
prefers-color-scheme media query
You can also set the theme according to the user agent settings. If you have the user agent set to dark, then this media query sets the styles to the dark theme. The media query accepts only light
and dark
as arguments:
: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";
}
}
/* element styles below */
Browser compatibility
Major web browsers pretty much share the same compatibility features.
On IoS, Safari is the only supported browser. When you install Chrome or Firefox, they use the Safari rendering engine.
For more info, read this.