What is CSS?
CSS stands for Cascading Style Sheets. It controls the presentation, appearance, and layout of HTML documents.
HTML provides structure and meaning. CSS controls how that structure is displayed.
p {
color: white;
font-size: 20px;
}
Learn CSS from selectors and the box model to responsive layouts, Flexbox, Grid, animations, and modern CSS.
CSS stands for Cascading Style Sheets. It controls the presentation, appearance, and layout of HTML documents.
HTML provides structure and meaning. CSS controls how that structure is displayed.
p {
color: white;
font-size: 20px;
}
<link rel="stylesheet" href="style.css">
<style>
p {
color: white;
}
</style>
<p style="color: white;">
Hello
</p>
External stylesheets are generally preferred for maintainability and reuse.
Selector
↓
Which elements?
Property
↓
What should change?
Value
↓
How should it change?
h1 {
color: orange;
}
selector {
property: value;
property: value;
}
color: red;
A declaration consists of a property and its value.
/* This is a CSS comment */
p {
color: white;
}
h1,
h2,
h3 {
color: white;
}
p {
color: white;
}
.card {
padding: 20px;
}
<div class="card">
Content
</div>
#header {
background: black;
}
* {
box-sizing: border-box;
}
input[type="email"] {
border: 1px solid gray;
}
.card.featured {
border: 2px solid orange;
}
<div class="card featured">
Featured card
</div>
h1,
h2,
h3,
p {
margin: 0;
}
article p {
color: gray;
}
Selects paragraphs anywhere inside an article.
article > p {
color: gray;
}
Selects only direct child paragraphs.
h2 + p {
margin-top: 0;
}
Selects a paragraph immediately following an h2.
h2 ~ p {
color: gray;
}
Selects paragraphs appearing later among the siblings of an
h2.
When multiple CSS rules target the same element, specificity helps determine which declaration wins when other cascade conditions do not resolve the conflict.
Inline styles
↓
ID selectors
↓
Class / attribute / pseudo-class selectors
↓
Element / pseudo-element selectors
p {
color: white;
}
.text {
color: yellow;
}
#intro {
color: orange;
}
If the same element has id="intro" and class="text", the ID selector has greater
specificity.
Keep selectors as simple as practical. Avoid building unnecessarily deep selectors that are difficult to override.
CSS stands for Cascading Style Sheets because multiple style rules can interact. The browser resolves conflicts using the cascade.
Some properties are inherited from a parent element by default.
body {
color: white;
font-family: sans-serif;
}
Child elements can inherit these values unless their own rules override them.
button {
color: inherit;
font: inherit;
}
.message {
color: red !important;
}
!important changes the cascade priority. Use it sparingly.
color: red;
background-color: black;
color: #ff0000;
color: #00ff00;
color: #0000ff;
color: rgb(255, 0, 0);
background: rgba(0, 0, 0, 0.5);
color: hsl(120, 100%, 50%);
button {
color: blue;
border: 2px solid currentColor;
}
width: 300px;
Pixels are commonly used when a fixed dimension is appropriate.
font-size: 1rem;
font-size: 1.5em;
rem is relative to the root font size, while em is relative to the relevant
inherited font size.
width: 100vw;
height: 100vh;
width: 50%;
Percentages are relative to an appropriate containing dimension or context.
min-height: 100svh;
min-height: 100lvh;
min-height: 100dvh;
body {
font-family: Arial, sans-serif;
}
h1 {
font-size: 3rem;
}
strong {
font-weight: 700;
}
p {
line-height: 1.6;
}
h1 {
letter-spacing: 0.05em;
}
text-align: left;
text-align: center;
text-align: right;
text-align: justify;
a {
text-decoration: none;
}
text-transform: uppercase;
┌─────────────────────────────┐
│ Margin │
│ ┌───────────────────────┐ │
│ │ Border │ │
│ │ ┌───────────────────┐ │ │
│ │ │ Padding │ │ │
│ │ │ ┌───────────────┐ │ │ │
│ │ │ │ Content │ │ │ │
│ │ │ └───────────────┘ │ │ │
│ │ └───────────────────┘ │ │
│ └───────────────────────┘ │
└─────────────────────────────┘
.box {
width: 300px;
height: 200px;
}
.box {
padding: 20px;
}
.box {
margin: 20px;
}
.box {
border: 1px solid black;
}
* {
box-sizing: border-box;
}
With border-box, declared width and height include the padding and border.
margin: 10px;
margin: 10px 20px;
margin: 10px 20px 30px;
margin: 10px 20px 30px 40px;
display: block;
The element participates in normal block layout and normally occupies available inline space.
display: inline;
display: inline-block;
display: none;
The element is removed from the layout.
overflow: hidden;
overflow: auto;
overflow: scroll;
overflow-x: auto;
overflow-y: hidden;
position: static;
position: relative;
top: 10px;
left: 10px;
A relatively positioned element remains in normal flow while its visual position can be offset.
.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
right: 0;
}
An absolutely positioned element is positioned relative to an appropriate containing block.
position: fixed;
bottom: 20px;
right: 20px;
position: sticky;
top: 0;
Sticky positioning combines normal-flow behavior with offset-based positioning during scrolling.
.modal {
position: fixed;
z-index: 1000;
}
z-index does not operate in a single global layer system. Certain CSS properties create
stacking contexts that affect how descendants are composited.
.header {
position: sticky;
top: 0;
z-index: 10;
}
.modal {
position: fixed;
inset: 0;
z-index: 1000;
}
Flexbox is a one-dimensional layout system for arranging items along a primary axis and a cross axis.
.container {
display: flex;
}
flex-direction: row;
flex-direction: row-reverse;
flex-direction: column;
flex-direction: column-reverse;
justify-content: flex-start;
justify-content: center;
justify-content: flex-end;
justify-content: space-between;
justify-content: space-around;
justify-content: space-evenly;
align-items: stretch;
align-items: flex-start;
align-items: center;
align-items: flex-end;
.container {
display: flex;
gap: 20px;
}
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1;
}
.item {
flex: 1 1 300px;
}
.special {
align-self: flex-end;
}
.nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
}
CSS Grid is a two-dimensional layout system for arranging content in rows and columns.
.container {
display: grid;
}
grid-template-columns: 200px 200px 200px;
grid-template-columns: 1fr 2fr;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
Modern CSS generally uses the gap property.
gap: 20px;
grid-template-rows: auto 1fr auto;
.item {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.cards {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.page {
display: grid;
grid-template-areas:
"header header"
"main sidebar"
"footer footer";
}
.header {
grid-area: header;
}
.main {
grid-area: main;
}
.sidebar {
grid-area: sidebar;
}
.footer {
grid-area: footer;
}
Responsive design allows a layout to adapt to different viewport sizes and devices.
.container {
width: min(100% - 32px, 1000px);
margin-inline: auto;
}
img {
max-width: 100%;
height: auto;
}
.cards {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 700px) {
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1000px) {
.cards {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 700px) {
body {
font-size: 16px;
}
}
@media (min-width: 700px) {
.layout {
display: grid;
}
}
@media (orientation: landscape) {
.hero {
min-height: 70vh;
}
}
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0s;
transition-duration: 0s;
}
}
@media (prefers-color-scheme: dark) {
body {
background: black;
color: white;
}
}
a:hover {
color: green;
}
button:focus {
outline: 2px solid blue;
}
input:focus-visible {
outline: 2px solid orange;
}
input:checked {
accent-color: green;
}
li:first-child {
font-weight: bold;
}
li:last-child {
margin-bottom: 0;
}
li:nth-child(2) {
color: orange;
}
button:not(.primary) {
background: gray;
}
.box:empty {
display: none;
}
h2::before {
content: "#";
margin-right: 8px;
}
a::after {
content: " ↗";
}
p::first-letter {
font-size: 2rem;
}
p::first-line {
font-weight: bold;
}
::selection {
background: orange;
color: black;
}
input,
textarea,
select,
button {
font: inherit;
}
input {
width: 100%;
padding: 10px 12px;
border: 1px solid gray;
border-radius: 5px;
}
input:focus-visible {
outline: 2px solid orange;
outline-offset: 2px;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
input[type="checkbox"],
input[type="radio"] {
accent-color: green;
}
background-color: black;
background-image: url("hero.jpg");
background-size: cover;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
background: linear-gradient(
90deg,
black,
gray
);
border: 1px solid black;
border-radius: 10px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.2);
text-shadow:
2px 2px 0 black;
transform: translateX(20px);
transform: translateY(10px);
transform: translate(20px, 10px);
transform: scale(1.1);
transform: rotate(45deg);
transform: skewX(10deg);
transform-origin: center;
button {
background: black;
transition: background 200ms ease;
}
button:hover {
background: gray;
}
button {
transition:
background 200ms ease,
transform 200ms ease;
}
button:hover {
transform: translateY(-2px);
}
transition: all 200ms ease;
Explicitly naming properties is often easier to reason about than transitioning everything.
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.box {
animation:
fade-in 500ms ease
both;
}
animation-name: fade-in;
animation-duration: 500ms;
animation-delay: 100ms;
animation-iteration-count: 2;
animation-direction: alternate;
animation-fill-mode: both;
animation-timing-function: ease;
animation-iteration-count: infinite;
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
:root {
--primary: #00ffaa;
--background: #333333;
--text: #eeeeee;
}
body {
background: var(--background);
color: var(--text);
}
a {
color: var(--primary);
}
color: var(--text-color, white);
.card {
--card-padding: 20px;
padding: var(--card-padding);
}
.dark {
--background: black;
--text: white;
}
.light {
--background: white;
--text: black;
}
width: calc(100% - 40px);
width: min(100%, 1000px);
width: max(300px, 50%);
font-size: clamp(1.5rem, 4vw, 3rem);
clamp() provides a minimum, preferred, and maximum value.
grid-template-columns:
repeat(auto-fit, minmax(220px, 1fr));
margin-inline: auto;
padding-block: 20px;
padding-inline: 30px;
Logical properties describe layout in terms of writing direction rather than assuming a specific physical direction.
.video {
aspect-ratio: 16 / 9;
}
img {
width: 100%;
height: 300px;
object-fit: cover;
}
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 500px) {
.card {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
:is(h1, h2, h3) {
line-height: 1.2;
}
:where(h1, h2, h3) {
margin-block: 0;
}
:where() is useful for grouping selectors while keeping their specificity very low.
.card:has(img) {
padding-top: 0;
}
#header {}
#main {}
#card {}
#button {}
Classes are usually more reusable and easier to compose.
color: red !important;
Excessive use makes the cascade difficult to reason about and override.
body main section article div ul li a {
color: red;
}
Prefer simpler selectors that directly express the component or state you need to style.
width: 1200px;
Fixed dimensions can create overflow and poor behavior on smaller screens. Prefer flexible sizing where appropriate.
Flexbox and Grid should generally handle normal page layout. Absolute positioning is better suited to overlays and precisely positioned elements.
button:focus-visible {
outline: 2px solid orange;
}
Keyboard users need a visible focus indicator.
@media (prefers-reduced-motion: reduce) {
* {
animation: none;
transition: none;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
>
<title>CSS Example</title>
<link rel="stylesheet" href="coding.css">
</head>
<body>
<header class="site-header">
<h1>Developer Notes</h1>
</header>
<main class="layout">
<section class="content">
<h2>CSS Layout</h2>
<div class="cards">
<article class="card">
<h3>Flexbox</h3>
<p>One-dimensional layouts.</p>
</article>
<article class="card">
<h3>Grid</h3>
<p>Two-dimensional layouts.</p>
</article>
</div>
</section>
<aside class="sidebar">
<h2>Resources</h2>
<a href="#">Documentation</a>
</aside>
</main>
</body>
</html>
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.layout {
width: min(100% - 32px, 1200px);
margin-inline: auto;
display: grid;
grid-template-columns: 1fr 300px;
gap: 30px;
}
.cards {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.card {
padding: 20px;
border: 1px solid gray;
}
@media (max-width: 800px) {
.layout {
grid-template-columns: 1fr;
}
}
p {}
.class {}
#id {}
* {}
[attr] {}
[attr="value"] {}
.parent .child {}
.parent > .child {}
h2 + p {}
h2 ~ p {}
button:hover {}
input:focus-visible {}
li:nth-child(2) {}
.card:has(img) {}
width: 300px;
height: 200px;
margin: 20px;
padding: 20px;
border: 1px solid black;
border-radius: 10px;
box-sizing: border-box;
font-family: sans-serif;
font-size: 1rem;
font-weight: 600;
line-height: 1.5;
letter-spacing: 0.02em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
gap: 20px;
flex: 1;
align-self: center;
display: grid;
grid-template-columns:
repeat(3, 1fr);
grid-template-rows:
auto 1fr;
gap: 20px;
grid-column: 1 / 3;
grid-row: 1 / 3;
position: relative;
position: absolute;
position: fixed;
position: sticky;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 10;
@media (max-width: 700px) {
...
}
@media (min-width: 700px) {
...
}
@media (prefers-reduced-motion: reduce) {
...
}
transform: translateY(-2px);
transform: scale(1.05);
transition: transform 200ms ease;
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.2);
width: calc(100% - 40px);
width: min(100%, 1000px);
width: max(300px, 50%);
font-size:
clamp(1.5rem, 4vw, 3rem);
grid-template-columns:
repeat(auto-fit, minmax(220px, 1fr));
Start with selectors, declarations, properties, values, comments, and basic rules.
Learn classes, IDs, attributes, combinators, pseudo-classes, and pseudo-elements.
Study inheritance, specificity, source order, and how conflicting rules are resolved.
Understand content, padding, border, margin, dimensions, and
box-sizing.
Practice fonts, sizes, weights, line height, spacing, alignment, and readable text layouts.
Master normal flow, display modes, positioning, Flexbox, and Grid.
Build layouts that adapt naturally using flexible dimensions, Grid, Flexbox, and media queries.
Practice backgrounds, borders, shadows, transforms, transitions, and animations.
Add logical properties, functions, container queries, custom properties, and modern selector features to your toolkit.
Build navigation bars, cards, dashboards, forms, landing pages, article layouts, and responsive applications.
Selector
↓
Find the element
Cascade
↓
Decide which rule wins
Box Model
↓
Understand size and spacing
Layout
↓
Arrange elements
Responsive Design
↓
Adapt to different screens
Visual Effects
↓
Create interaction and polish
1. Start with semantic HTML
2. Establish box-sizing and base styles
3. Define typography
4. Build the main layout
5. Use Flexbox or Grid for components
6. Add responsive behavior
7. Add states such as hover and focus
8. Add transitions only where useful
9. Test keyboard accessibility
10. Test different viewport sizes
11. Simplify selectors and remove unnecessary rules
HTML
Structure + Meaning
↓
CSS
Presentation + Layout
↓
JavaScript
Behavior + Interaction