Marcin Jahn | Dev Notebook
  • Home
  • Programming
  • Technologies
  • Projects
  • About
  • Home
  • Programming
  • Technologies
  • Projects
  • About
  • An icon of the Core section Core
    • Programs Execution
    • Stack and Heap
    • Asynchronous Programming
      • Overview
      • Event Queues
      • Fibers
      • Stackless Coroutines
  • An icon of the .NET section .NET
    • HTTPClient
    • Async
      • How Async Works
      • TAP Tips
    • Equality
    • Comparisons
    • Enumerables
    • Unit Tests
    • Generic Host
    • Logging
    • Configuration
    • Records
    • Nullability
    • Garbage Collector
    • IL and Allocations
    • gRPC
    • Source Generators
    • Platform Invoke
    • ASP.NET Core
      • Overview
      • Middleware
      • Razor Pages
      • Routing in Razor Pages
      • Web APIs
      • Filters
      • Identity
      • Validation
      • Tips
    • Entity Framework Core
      • Overview
      • Testing
      • Tips
  • An icon of the Angular section Angular
    • Overview
    • Components
    • Directives
    • Services and DI
    • Routing
    • Observables (RxJS)
    • Forms
    • Pipes
    • HTTP
    • Modules
    • NgRx
    • Angular Universal
    • Tips
    • Standalone Components
  • An icon of the JavaScript section JavaScript
    • OOP
    • JavaScript - The Weird Parts
    • JS Functions
    • ES Modules
    • Node.js
    • Axios Tips
    • TypeScript
      • TypeScript Environment Setup
      • TypeScript Tips
    • React
      • React Routing
      • MobX
    • Advanced Vue.js Features
  • An icon of the Rust section Rust
    • Overview
    • Cargo
    • Basics
    • Ownership
    • Structures
    • Enums
    • Organization
    • Collections
    • Error Handling
    • Generics
    • Traits
    • Lifetimes
    • Closures
    • Raw Pointers
    • Smart Pointers
    • Concurrency
    • Testing
    • Tips
  • An icon of the C/C++ section C/C++
    • Compilation
    • Structures
    • OOP in C
    • Pointers
    • Strings
    • Dynamic Memory
    • argc and argv Visualization
  • An icon of the GTK section GTK
    • Overview
    • GObject
    • GJS
  • An icon of the HTML & CSS section HTML & CSS
    • HTML Foundations
    • CSS Foundations
    • Responsive Design
    • CSS Tips
  • An icon of the Unity section Unity
    • Unity
  • An icon of the Functional Programming section Functional Programming
    • Fundamentals of Functional Programming
    • .NET Functional Features
    • Signatures
    • Function Composition
    • Error Handling
    • Partial Application
    • Modularity
    • Category Theory
      • Overview
      • Monoid
      • Other Magmas
      • Functors
  • An icon of the Algorithms section Algorithms
    • Big O Notation
    • Array
    • Linked List
    • Queue
    • Hash Table and Set
    • Tree
    • Sorting
    • Searching
  • An icon of the Architecture section Architecture
    • What is architecture?
    • Domain-Driven Design
    • ASP.NET Core Projects
  • An icon of the Core section Core
    • Programs Execution
    • Stack and Heap
    • Asynchronous Programming
      • Overview
      • Event Queues
      • Fibers
      • Stackless Coroutines
  • An icon of the .NET section .NET
    • HTTPClient
    • Async
      • How Async Works
      • TAP Tips
    • Equality
    • Comparisons
    • Enumerables
    • Unit Tests
    • Generic Host
    • Logging
    • Configuration
    • Records
    • Nullability
    • Garbage Collector
    • IL and Allocations
    • gRPC
    • Source Generators
    • Platform Invoke
    • ASP.NET Core
      • Overview
      • Middleware
      • Razor Pages
      • Routing in Razor Pages
      • Web APIs
      • Filters
      • Identity
      • Validation
      • Tips
    • Entity Framework Core
      • Overview
      • Testing
      • Tips
  • An icon of the Angular section Angular
    • Overview
    • Components
    • Directives
    • Services and DI
    • Routing
    • Observables (RxJS)
    • Forms
    • Pipes
    • HTTP
    • Modules
    • NgRx
    • Angular Universal
    • Tips
    • Standalone Components
  • An icon of the JavaScript section JavaScript
    • OOP
    • JavaScript - The Weird Parts
    • JS Functions
    • ES Modules
    • Node.js
    • Axios Tips
    • TypeScript
      • TypeScript Environment Setup
      • TypeScript Tips
    • React
      • React Routing
      • MobX
    • Advanced Vue.js Features
  • An icon of the Rust section Rust
    • Overview
    • Cargo
    • Basics
    • Ownership
    • Structures
    • Enums
    • Organization
    • Collections
    • Error Handling
    • Generics
    • Traits
    • Lifetimes
    • Closures
    • Raw Pointers
    • Smart Pointers
    • Concurrency
    • Testing
    • Tips
  • An icon of the C/C++ section C/C++
    • Compilation
    • Structures
    • OOP in C
    • Pointers
    • Strings
    • Dynamic Memory
    • argc and argv Visualization
  • An icon of the GTK section GTK
    • Overview
    • GObject
    • GJS
  • An icon of the HTML & CSS section HTML & CSS
    • HTML Foundations
    • CSS Foundations
    • Responsive Design
    • CSS Tips
  • An icon of the Unity section Unity
    • Unity
  • An icon of the Functional Programming section Functional Programming
    • Fundamentals of Functional Programming
    • .NET Functional Features
    • Signatures
    • Function Composition
    • Error Handling
    • Partial Application
    • Modularity
    • Category Theory
      • Overview
      • Monoid
      • Other Magmas
      • Functors
  • An icon of the Algorithms section Algorithms
    • Big O Notation
    • Array
    • Linked List
    • Queue
    • Hash Table and Set
    • Tree
    • Sorting
    • Searching
  • An icon of the Architecture section Architecture
    • What is architecture?
    • Domain-Driven Design
    • ASP.NET Core Projects

CSS Foundations

This is a kind of vocabulary listing explaining the most fundamental (or a bit more specific) CSS concepts

Cascade

It’s the first “C” in the CSS. It’s not about inheritance (inheritance is a separate concept of CSS). Cascade is about resolving conflicts in our stylesheets (or actually not only ours, because User Agent (UA) stylesheets are also considered). Cascade is an ordered list of style sheets. They all get combined and conflicts get resolved automatically. Various primitives may influence the ordering and conflict resolution:

  • !important - prioritizes rules. UA rules that are !important take precedence over author !important declarations. The use of !important is really valid only when you do not have control over the entire style sheet. Otherwise, it shows potential issues in your CSS design.
  • specificity - Specificity has 3 values, which get combined into a 3-digit number. The higher the number, the higher the specificity (and priority of the rule). :where might be used to avoid specificity.
  • @layer - allows to explicity specify the order of various style sheets, including imported ones.

Imports

Imports work as if you just copied and pasted the contents of imported file in place of the @import declaration. Frameworks that compile down to CSS, like SCSS have different primitives for importing, like @use.

Inheritance

In CSS, various properties get inherited by children elements. Not all properties work this way. You can find out if a given property is inheritable in the CSS specs (e.g. text-indent is not inheritable) We can make any property inheritable by using inherit value for such property (it will inherit from direct parent only though).

Pseudo

Pseudo-classes are selectors that use information inferred from the document, and not just the authored markup itself. E.g., it could information whether some element is hovered.

:is() pseudo-class allows us to group specifiers.

Example:

:is(ul, ol) li

This is the same as:

ul li, ol li

This avoids some repetition.

Pseudo-elements are elements that are not defined explicitly in the document, but they do exist and we might want to select them. Example is ::first-letter.

Engines

Web engines look at the selectors from right to left. Each time they move to the left they filter. So, in general, the right-most part should be the most limiting for efficiency.

ul * is worse than * in terms of performance for example (these are not equivalent markups, it’s just an example).

Box Model

Box Model is the Visual Formatting Model (VFM) of CSS. CSS operates on boxes that it creates layout from.

Intrinsic Size

It’s a size of element calculated based on its content, not on explicit size specification.

Box Sizing

By deafult, box-sizing seaprates width, padding and border. Setting width sets it only on the content alone. box-sizing: border-box changes that, and it is a popular setting to use.

Reference Pixel and Relative Units

1 px = 1.96 inch. In CSS, we do not deal with real pixels, but rather with these reference pixels.

em is a relative unit. n em means: whatever px size we’d normally get for this element, multiply it by n. rem is simpler - it just scales against the root element font size of the page.

Auto

Various CSS properties accept auto as a value. It has different meaning for different properties, so it’s best to check in the specs what it means for a given property.

Flow

When we talk about flow of elements in CSS, we mostly talk about the display proprty. Different values of this property decide how elements flow in the box model of CSS. The display property decides how children of the element are laid out - it’s the inner display type. At the same time, it sets the outer display type as well, that is how this element behaves in relation to the boxes around it.

/* Full format */
<ELEMENT > {
display: <outer> <innter>;
}
/* Shorthand */
<ELEMENT > {
display: <value>;
}

The shorthand format is more popular, and it actually sets both outer and inner display type behind the scenes. E.g., display: block; is the same as display: block flow; (block is outer, and flow is inner). flow means that the children of this element will behave as defined by their display.

The outer display type is either block or inline. Inner has much more options, like flex, grid, table, flow, flow-root, and others.

Example: display: flex is really display: block flex. Some <div style="display: flex;"> would then be placed on a new line (like a block), but its children will follow the flexbox principles.

Block Display

Boxes are laid out one after the other in “vertical” direction (block direction really). The “vertical” margins collapse. By default, block elements consume all space in the “horizontal” (inline) direction.

When I say “vertical”, I really mean block direction. It’s just easier to visualize concepts with concrete direction. In this text and others on this site, I assume an English writing system where text goes from left-to-right, and paragraphs appear from top to bottom.

Inline Display

Boxes are laid out “horizontally” (in inline direction really). Elements positioned inline are placed within a Line Box (which could be seen as a pseudo-element). Line Box is constrained horizontally by container width and by floated elements. line-height is a height of a single Line Box.

A text in HTML can be seen as a collection of elements (characters) which are inlined.

text-align and vertical-align behave a bit like flexbox properties.

flow-root Display and BFC

It establishes a new Block Formatting Context (BFC). It means that its children cannot overflow and go outside of it. <html> creates a BFC as well. Setting overflow (to anything other than visible and clip) also does.

Vertical and Hotizontal?

Looking at Block and Inline display as vertical and horizontal is an old way of looking at this matter. We have to consider other writing systems where characters appear from right to left or even vertically. With that in mind, the block and inline directions might vary.

We can set the writing mode with writing-mode, e.g. writing-mode: vertical-lr. “vertical” is the inline direction and “lr” (left to right) is a block direction.

Using words such as “top”, “bottom”, “left” and “right” is problematic, because it makes our styles fixed with some particular writing system (most often left-to-right). If we ever decide to add support for another writing system we’ll be a bit screwed, and we’ll have to adjust a ton of styles.

To avoid such issues, there’s alternative namings for varius directional properties:

  • left - inline-start
  • right - inline-end
  • top - block-start
  • bottom - block-end
  • width - inline-size
  • height - block-size

Example: m, but its children will follow the flexbox principles.argin-right becomes margin-inline-end.

Formatting Context

Everything on a page is part of formatting context. The rooth <html> element establishes to initial block formatting context.

There are many types of formatting context, like block, inline, flex.

Block Formatting Context

Elements within a block formatting context are layed out according to Normal Flow. Everything that is within the block formatting context needs to fit in that. So, if there is some element that is out of flow (like an absolutely positioned box or some floated box), it will be within the closest block formatting context.

Block formatting context might be established in various ways, also “incidentally”, like by setting any non-default overflow property value. An explicit way to create a new block formatting context is by setting display: flow-root. Its named this way, because creating a new block formatting context is kind of like creating a new root (like <html> is one).

For example, if we have the following arrangement:

<div style="background: green; width: 200px;">
<div style="float: left; background: blue; width: 50px;">
a float that goes below the parent
</div>
<div>Some loooooooooong text</div>
</div>

a float that goes below the parent

Some loooooooooong text

The floated box goes out of its container. It’s still within its closes block formatting context (could be <html>).

We can fix it by making the container a new block formatting context:

<div style="display: flow-root;">
<div style="background: green; width: 200px; display: flow-root">
<div style="float: left; background: blue; width: 50px;">
a float that goes below the parent
</div>
<div>Some loooooooooong text</div>
</div>
</div>

a float that goes below the parent

Some loooooooooong text

Now the floated box is contained completely within its container, because a BFC has to include all of its children completely.

Inline Formatting Context

Inline formatting context exists within other formattig context (opposed to BFC, which exists as a root). In this context, horizontal padding, border and margin will be applied, pushing horizontal content. However, vertical padding, border and margin will not push other Line Boxes away. So, for example, a border would just be drawn on top of other Line Boxes:

<p>
This is placeholder text. It is used to fill a space in a design where the
final content is not yet available. Using
<span style="padding: 20px; border: 1px solid black;">placeholder</span> text
allows designers and developers to see how the layout will look with text,
without being distracted by the actual content. This makes it easier to focus
on the visual aspects of the design, such as typography, spacing, and color.
</p>

This is placeholder text. It is used to fill a space in a design where the final content is not yet available. Using placeholder text allows designers and developers to see how the layout will look with text, without being distracted by the actual content. This makes it easier to focus on the visual aspects of the design, such as typography, spacing, and color.


Other formatting context (like flex) are not part of normal flow.

Stacking Context

z-index is all about the order of painting of elements on the screen. There can be many stacking contexts. Each positioned element creates a new stacking context. Different stacking contexts are separated from one another and their z-index values do not compare. z-index values are compared only within the same stacking context.

A new stacking context can also be created with the isolation: isolate property. It’s kind of similar to how a new BFC mightr be created “incidentally” by various CSS properties, but there’s a dedicated display: flow-root setting for creating a BFC. isolation: isolate has similar story. “Incidental” stacking context might be created by setting opacity, or by setting z-index on flex item, and in many other ways.

The root <html> element creates a first stacking context.

←  HTML Foundations
Responsive Design  →
© 2025 Marcin Jahn | Dev Notebook | All Rights Reserved. | Built with Astro.