1. Viewport-dependent units: vh and vw
Units that depend on the browser window (viewport) dimensions:
| Unit | Value |
|---|---|
1vh |
1% of the browser window height |
1vw |
1% of the browser window width |
100vh instead of height: 100%
To make a block take up the full screen height via height: 100%, you have to set height: on every parent element in the chain (html, body, wrappers). This is unreliable and ties the styling rigidly to the markup.
100%
100vh solves this in a single line without depending on parents:
.hero {
height: 100vh; /* Full window height */
}
The vw problem and the scrollbar
100vw is 100% of the window width without accounting for the scrollbar. If the page has a vertical scrollbar (Windows, Linux), 100vw will be larger than the available width, which causes horizontal scrolling.
On macOS and mobile devices the scrollbar overlays the content, so the problem does not arise. But on Windows/Linux the scrollbar takes up space (~17px).
Conclusion: 100vw ≠ 100%. For width it is usually better to use percentages.
2. The vmin and vmax units
| Unit | Value |
|---|---|
1vmin |
1% of the smaller of the two values (window width or height) |
1vmax |
1% of the larger of the two values (window width or height) |
How it works when orientation changes
| Orientation | vmin behaves like | vmax behaves like |
|---|---|---|
| Landscape (width > height) | vh |
vw |
| Portrait (height > width) | vw |
vh |
Example: a responsive heading
.hero__title {
font-size: 15vmin; /* Auto-scales in any orientation */
}
Instead of two media queries for portrait and landscape orientation, vmin automatically picks the smaller dimension.
3. Limitations of viewport-dependent units
Viewport units are not suitable for building an entire site:
- There is no real dependency between font size and window height — on 1080px and 900px screens the difference is minimal
- You cannot match the design layout — pixel sizes become unpredictable
- Mobile devices with similar widths (360px vs 375px) will get a different, but needlessly different, size
Where viewport units are appropriate:
100vh— full-screen sections (hero blocks)80vh— large blocks tied to the window height- Projects without a strict design layout, where basic responsiveness is needed
The main units remain px, %, em, rem.
4. The rem approach: one value for all devices
The idea: write all sizes in rem without a media query, and in the media queries change only the font-size of the <html> tag.
Desktop First approach (pixels)
/* Lots of styles in each media query */
@media (min-width: 1024px) {
.card__title { font-size: 22px; }
.card__text { font-size: 16px; }
.card { padding: 20px; }
}
@media (max-width: 480px) {
.card__title { font-size: 18px; }
.card__text { font-size: 14px; }
.card { padding: 12px; }
}
The rem approach
/* All sizes — without a media query */
.card__title { font-size: 2.2rem; }
.card__text { font-size: 1.6rem; }
.card { padding: 2rem; }
/* In the media queries — only html font-size */
@media (min-width: 1024px) {
html { font-size: 10px; }
}
@media (max-width: 480px) {
html { font-size: 8px; }
}
Advantages: to scale up everything on the site — you just change the font-size of the html tag. To scale up a single element — change its value in rem.
5. User font size and percentages
By default the font-size in the browser = 16px. Users with visual impairments can change this value in their settings.
If we set html { font-size: 10px; } — the user’s settings are ignored. To preserve them, we use percentages:
Recalculating into percentages
- To get 10px out of 16px: 10 / 16 = 62.5%
- To get 8px out of 16px: 8 / 16 = 50%
@media (min-width: 1024px) {
html { font-size: 62.5%; } /* = 10px of 16px */
}
@media (max-width: 480px) {
html { font-size: 50%; } /* = 8px of 16px */
}
Now if the user changes the base size from 16px to 32px, our rem values will also scale up proportionally.
6. Fractional pixels: why we round
Each pixel on the screen is a set of physical lamps (RGB). You cannot light up 0.18 of a lamp. That is why all pixel values must be whole numbers.
When a calculation produces a fractional number (for example, 8.18px), it needs to be rounded to a whole number. The browser will do this itself, but it is better to control the result.
7. Ctrl+/- is not zoom
An important distinction between two ways of scaling:
| Method | What happens |
|---|---|
| Zoom (pinch-to-zoom, trackpad) | The page enlarges like an image, the layout does not change |
| Ctrl+/Ctrl- | The viewport shrinks — media queries fire, the mobile version may open |
With Ctrl+ on a 2K monitor, window.innerWidth may show 853px instead of the real 2560px. The markup must work correctly in this mode too.
8. Accessibility (a11y)
The internet is a basic need for all people, regardless of physical characteristics. The main accessibility tools:
- ARIA attributes — describe elements for screen readers
- The alt attribute for
<img>— mandatory: the reader announces this text, and it is also shown when the image fails to load - The title attribute — a tooltip on hover, works for any element
- Increasing the font — in the browser or system settings; rem units ensure correct scaling
9. Web app vs. website
| Characteristic | Website | Web application (Web App) |
|---|---|---|
| UX (experience) | Viewing pages, following links | Like a native app: swipes, animations, offline |
| Examples | News sites, blogs | Twitter, Gmail, Figma |
| Add to Home Screen | Opens in the browser | Opens as a full-fledged app (without the address bar) |
Modern JavaScript (React, React Native) makes it possible to create web apps with a UX identical to native apps.
10. Summary table
| Topic | Key point |
|---|---|
| vh / vw | 1% of viewport height / width; 100vw ≠ 100% because of the scrollbar |
| vmin / vmax | 1% of the smaller / larger viewport dimension; automatic adaptation to orientation |
| Limitations of viewport units | Not suitable for a whole site; appropriate for hero blocks (100vh) and projects without a layout |
| The rem approach | All sizes in rem, in media queries — only html font-size |
| html font-size in % | 62.5% = 10px; preserves the user’s accessibility settings |
| Rounding pixels | Fractional px values need to be rounded — you cannot light up 0.18 of a lamp |
| Ctrl+/- vs Zoom | Ctrl+/- changes the viewport (media queries fire); zoom scales like an image |