Building a Responsive Layout

Lecture notes: cross-browser compatibility, caniuse.com, vendor prefixes, responsive layout strategies

1. Cross-browser compatibility and caniuse.com

Cross-browser compatibility is a site’s ability to display correctly across different browsers. It’s one of the most common problems web-layout developers face.

The caniuse.com service lets you check whether any CSS/HTML/JS technology is supported in modern browsers. You enter the name of a technology and see a full breakdown of support across browser versions.

Use cases:

  • Checking support for CSS Custom Properties (variables)
  • Checking support for -webkit-line-clamp
  • Checking support for the <picture> tag
  • Checking new CSS/JS features

2. Vendor prefixes

Vendor prefixes are special prefixes added to CSS properties that browsers used for experimental features:

  • -webkit- — Chrome, Safari, newer versions of Opera
  • -moz- — Firefox
  • -o- — older versions of Opera
  • -ms- — Internet Explorer, Edge (older)

Originally these prefixes were created to showcase upcoming features. Over time developers began using them as full-fledged properties, which led to compatibility problems.

Example of a property with a vendor prefix:

.element {
-webkit-line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
}

Today most properties are supported without prefixes. Check the current status on caniuse.com.

3. Truncating text: text-overflow and line-clamp

Single-line truncation with an ellipsis

To truncate text to a single line with an ellipsis, you need a combination of three properties:

.truncate {
white-space: nowrap;        /* Prevent line wrapping */
overflow: hidden;           /* Hide the overflow */
text-overflow: ellipsis;    /* Add the ellipsis */
}

All three properties are required — without any one of them, the effect won’t work.

Multi-line truncation with -webkit-line-clamp

To truncate after a certain number of lines, use -webkit-line-clamp:

.multiline-truncate {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;    /* Number of lines */
overflow: hidden;
}

Despite the -webkit- prefix, this property works in all modern browsers.

4. BrowserHacks (CSS hacks)

BrowserHacks is a collection of CSS/JS workarounds for targeting a specific browser or version. These are special constructs with no logical meaning that only work in certain browsers.

Example of a hack for targeting Chrome:

/* Applies only in Chrome */
@media screen and (-webkit-min-device-pixel-ratio: 0) {
.element {
color: red;
}
}

Using hacks is not recommended — it indicates low-quality markup. If you still have to, always leave comments in the code.

5. Layout types: responsive, adaptive, fluid

Fluid layout (Fluid/Liquid)

The site stretches together with the browser window. All blocks have relative sizes (in percentages). An example is Wikipedia.

The problem: on very wide screens the text becomes hard to read — the lines are too long. Solutions:

  • Limit the maximum width (max-width)
  • Split the text into columns (CSS columns)

Responsive layout (Responsive)

The site rearranges itself as the window width changes, using media queries. Elements change their position, size, and visibility. This is the most common approach.

overflow: hidden as a workaround

A common mistake — instead of finding the cause of horizontal scrolling, developers put overflow: hidden on the body. This only masks the problem rather than solving it.

6. CSS debugging with outline

A quick way to visualize the markup in order to find the cause of overflow or shifting — add an outline to all elements:

The outline method

/* Outline every element — doesn't affect sizes */
* {
outline: 1px solid red;
}

The semi-transparent background method

/* Each nested level becomes darker */
* {
background: rgb(0 0 0 / 0.1);
}
Why outline and not border? outline doesn’t affect block sizes and doesn’t shift neighboring elements — you see the real layout. border adds thickness and can change layout behavior.

7. Practical example: a responsive user card

Let’s look at the markup for a card that, on desktop, shows the photo, name, job title, and contacts vertically, and on mobile — a full-screen photo with overlaid text.

HTML structure

<div class="card">
<img class="card__image"
src="photo.jpg"
alt="Photo">
<div class="card__info">
<h2 class="card__name">Jane Smith</h2>
<p class="card__post">Photographer</p>
<a class="card__contact" href="tel:+380501234567">+380 50 123 45 67</a>
<a class="card__contact" href="mailto:test@example.com">test@example.com</a>
</div>
</div>

Desktop version (object-fit: cover)

.card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
text-align: center;
background: blue;
color: white;
}
.card__image {
width: 100px;
height: 100px;
object-fit: cover;        /* Preserve proportions */
border-radius: 50%;       /* Circle */
border: 4px solid white;
}

Mobile version (layers with position and z-index)

.card {
position: relative;
}
.card__image {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
.card__info {
position: relative;
z-index: 2;
background: rgba(0, 0, 255, 0.5);   /* Semi-transparent background */
}

The key technique: the image stretches across the whole block via position: absolute, while the text block with a higher z-index is overlaid on top with a semi-transparent background.

8. CSS triangles with border

When an element has zero width and height while its borders are large, each of the four borders forms a triangle:

.triangle {
width: 0;
height: 0;
border-width: 100px;
border-style: solid;
border-color: red green blue black;
}

To keep just one triangle, we make the remaining borders transparent:

/* Triangle pointing right */
.triangle-right {
width: 0;
height: 0;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 100px solid green;
border-right: 0;
}

Triangles are used for dropdown-menu arrows, tooltips, and composite shapes (trapezoids and the like). The technique is simple and requires no images.

9. Pill shape with border-radius

A pill button is an element with fully rounded ends. A common mistake is to use border-radius: 50%, which turns a rectangle into an oval.

/* Problem: 50% makes an oval, not a pill */
.oval {
border-radius: 50%;    /* Oval shape */
}
/* Solution: a large value creates perfect rounding */
.pill {
border-radius: 100vw;  /* Always a perfect pill */
}

The value 100vw is deliberately larger than any possible radius — the browser automatically clamps it to half of the element’s smallest dimension. The result is perfectly rounded ends regardless of width or height.

Shape variations

/* Dome (rounding only on top) */
.dome {
border-radius: 100vw 100vw 0 0;
}

10. Logical operators in media queries

Comma (OR — logical OR)

Combines several independent media queries. The styles apply if at least one of them is true:

@media (max-width: 600px), (orientation: portrait) {
/* Applies at a width up to 600px OR in portrait orientation */
}

and (logical AND)

Combines conditions — the styles apply only when all conditions are true at the same time:

@media (min-width: 768px) and (max-width: 1024px) {
/* Only for widths from 768px to 1024px */
}

not (logical NOT)

Negation — the styles apply to every case except the specified one:

@media not print {
/* For all devices except print */
}

In practice, the Mobile First approach with min-width is usually enough. Logical operators are rarely needed, but it’s useful to know they exist.

11. Full-screen background: background-size: cover

To create a full-screen block with a background image, use this combination:

.hero {
height: 100vh;                    /* The full window height */
background-image: url('hero.jpg');
background-size: cover;            /* Fills the whole block */
background-position: center;
background-repeat: no-repeat;
}

cover guarantees the image fills the entire block without distortion, cropping the excess. contain, by contrast, fits the whole image but may leave empty strips.

For responsive mobile versions it’s better to use the <picture> tag, which lets you load different images for different screen sizes.

12. 100vh for full-screen sections

To create a block that fills the whole window height, developers use the vh unit:

.fullscreen-section {
height: 100vh;   /* 100% of viewport height */
}

The 100vh problem on mobile devices

Mobile browsers have an address bar and a navigation panel that can hide as you scroll. The classic value 100vh always equals the window height without accounting for these panels — that is, it’s the largest possible viewport height. Because of this, on mobile 100vh can be larger than the visible area, and content spills off-screen.

New viewport units: svh, lvh, dvh

To solve this problem, three new viewport-height units were introduced in CSS:

Unit Name What it means
svh Small Viewport Height Viewport height when all browser panels are shown (the smallest visible area)
lvh Large Viewport Height Viewport height when all browser panels are hidden (the largest visible area)
dvh Dynamic Viewport Height Changes dynamically as browser panels appear/disappear
On mobile browsers the classic vh value behaves like lvh — it always equals the largest viewport size.

How to choose the right unit

  • dvh — the best choice for full-screen sections (hero blocks, landing pages). Content always fits the visible area exactly, even when the address bar is shown
  • svh — guarantees content will never be cut off, even when the panels are maximally visible. Useful for elements where clipping is critical (for example, a login form or a CTA button)
  • lvh — behaves identically to the classic vh. Rarely needed on its own, but can be useful if you deliberately want to use the maximum height

Usage example

/* Hero block that always occupies the entire visible screen */
.hero {
min-height: 100dvh;
}
/* Fallback for older browsers */
.hero {
min-height: 100vh;    /* Older browsers */
min-height: 100dvh;   /* Modern browsers */
}
The dvh unit changes dynamically on scroll as browser panels hide. This can cause unwanted reflow of elements. So for animations and fixed elements it’s better to use svh or lvh, which have a stable value.

Equivalent units for width

The same variants exist for viewport width too: svw, lvw, dvw. There are also the inline units svi, lvi, dvi and the block units svb, lvb, dvb, which account for the text direction. In practice these units are rarely needed for width, since browser panels usually affect only the height.

13. The modular grid

A modular grid is the division of space into equal columns against which content is placed. This concept comes from typography (newspapers, magazines, encyclopedias).

The standard is 12 columns, because 12 is divisible by 2, 3, 4, and 6:

Division Modules Percentages
Into 2 parts 6 + 6 50% + 50%
Into 3 parts 4 + 4 + 4 33.33% + 33.33% + 33.33%
Into 4 parts 3 + 3 + 3 + 3 25% + 25% + 25% + 25%
Sidebar + content 3 + 9 25% + 75%
Content + sidebar 8 + 4 66.67% + 33.33%

Advantages of the modular grid:

  • Easier to align elements — we think in modules, not pixels
  • Percentages become clear: 6 of 12 = 50%, 4 of 12 = 33.33%
  • Easier for the designer and the layout developer to communicate

14. Bootstrap: grid and components

Framework vs library

A framework (Bootstrap) is a comprehensive solution: a grid plus components (buttons, modals, carousels, accordions, and so on). A library (FlexboxGrid) solves a single task (for example, just the grid).

Adding Bootstrap

<!-- CSS -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
<!-- JS (for interactive components) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>

Container (container)

The container class creates a centered column with a fixed width for each breakpoint:

Window width Container width
< 576px 100%
≥ 576px 540px
≥ 768px 720px
≥ 992px 960px
≥ 1200px 1140px
≥ 1400px 1320px

Breakpoints

Prefix Minimum width Name
(no prefix) < 576px Extra small
sm ≥ 576px Small
md ≥ 768px Medium
lg ≥ 992px Large
xl ≥ 1200px Extra large
xxl ≥ 1400px Extra extra large

Grid System

Bootstrap uses a containerrowcol system:

<div class="container">
<div class="row">
<div class="col-8">8 of 12 modules (66.67%)</div>
<div class="col-4">4 of 12 modules (33.33%)</div>
</div>
</div>

Responsive columns

By adding a breakpoint prefix, we set a different number of modules for different devices:

<div class="row">
<!-- On sm and up: 8 modules, below sm: 100% -->
<div class="col-sm-8">Main content</div>
<div class="col-sm-4">Sidebar</div>
</div>
<div class="row">
<!-- Several breakpoints at once -->
<div class="col-12 col-sm-8 col-md-6 col-lg-4">
Responsive block
</div>
</div>

When to use Bootstrap

  • Admin panels (where the design isn’t critical)
  • Rapid prototyping to show a client
  • Large portals with repeating components
  • Projects where most Bootstrap components are genuinely needed

15. FlexboxGrid

FlexboxGrid is a lightweight library that implements only a modular grid based on Flexbox. Its classes are practically identical to Bootstrap: container, row, col.

Usage example:

<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6 col-lg-4">
Content
</div>
</div>

Suitable when you only need a grid without components. For modern projects, also consider CSS Grid Layout as a native alternative.

16. Rules for naming CSS classes

What NOT to do

  • Don’t name classes after colors: .red-button → better .button-danger or .button-primary. The color theme may change
  • Don’t put tags in class names: .div-header → better .header. The tag may change
  • Don’t use sequential numbers: .item-1, .item-2 → when adding new elements, the numbering loses its meaning
  • Don’t combine unrelated blocks: .header, .footer, .sidebar { width: 100%;
    }
    → keep block styles separate

What TO do

  • Use semantic names: .card__image, .nav__link
  • One class = one selector: the best selector is a single class with no nesting
  • Stick to a single separator style: if you use a hyphen — use it everywhere; if camelCase — everywhere
  • The BEM methodology: Block__Element–Modifier — a proven approach to naming
  • Move logic into HTML: instead of :nth-child, better add a .item--first class

Simplicity of code

The simpler your CSS rules, the easier it is for other developers (and for you yourself later) to understand the code. Simple code is also processed faster by the browser.

17. Simplifying modifier classes

When you have a block with several style variants (modifiers), you usually use a base class plus a modifier class:

<button class="btn btn-primary">Save</button>
<button class="btn btn-danger">Delete</button>
<button class="btn btn-outline">Cancel</button>

Instead of writing separate styles for each modifier, you can use the [class|="btn"] selector, which selects every element whose class starts with the word btn:

/* Base styles for all btn-* */
[class|="btn"] {
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
/* Specific modifiers */
.btn-primary { background: #3b82f6; }
.btn-danger { background: #ef4444; }
.btn-outline { border: 1px solid currentColor; }
Warning: the [class|="btn"] selector only works when btn is the first word in the class attribute. If an element has class="card btn-primary", this selector will not select it. For such cases it’s better to use [class*="btn-"].

18. scroll-behavior: smooth

A CSS property for smooth scrolling when following anchor links:

html {
scroll-behavior: smooth;
}

After this, clicks on anchor links (for example, <a href="#section">) will smoothly scroll the page to the target element instead of jumping abruptly.

19. Site loading speed

The loading-speed formula:

Time = Number of files × File size + Processing complexity

How to influence each component:

  • Number of files: combining CSS/JS files, using sprites/SVG instead of separate icons
  • File size: minification, image compression, lazy loading
  • Complexity: simpler CSS selectors, fewer animations, Critical CSS

20. Summary table

Topic Key point
caniuse.com Checking technology support across browsers
Vendor prefixes -webkit-, -moz-, -o-, -ms-
text-overflow: ellipsis + white-space: nowrap + overflow: hidden
-webkit-line-clamp Multi-line truncation with an ellipsis
Layout types Fluid, responsive
CSS debugging with outline * { outline: 1px solid red; } — see the boundaries of all elements
object-fit: cover Filling a block with an image while preserving proportions
CSS triangles border + width: 0 + height: 0 + transparent
Pill shape border-radius: 100vw — perfectly rounded ends
Logical operators Comma (OR), and (AND), not (NOT)
background-size: cover Full-screen background without distortion
100vh / dvh / svh / lvh Viewport units: classic, dynamic, small, large height
Modular grid 12 columns, came from typography
Bootstrap Framework: grid + components
FlexboxGrid Library: grid only
Class naming No colors, tags, or numbers; BEM; simple selectors
Modifier classes [class|="btn"] — shared styles for all btn-*
scroll-behavior smooth — smooth scrolling to anchors

Vitalii Kaplia

Founder, Web Developer & WordPress Expert

I became interested in programming back in 1997. The first acquaintance with a future profession was using Visual Basic. In…

More about author

A digital product engineer and web solutions architect

Free consultation + cost calculation

Let’s discuss your project?

Free consultation + cost calculation

More interesting articles

Customer login

This site uses cookies

We use cookies to personalize content and ads, provide social media features, and analyze our traffic. We also share information about your use of our website with our social media, advertising, and analytics partners, who may combine it with other information you have provided to them or collected when you use their services. By continuing to use our site, you consent to our use of cookies and accept our Privacy Policy and Terms of Use.

Virtual assistant
Hi! I'm the KAPLIA.PRO virtual assistant! I can tell you about our services, portfolio projects, ballpark pricing, and how we work — from websites and eCommerce to web apps, CRMs, bots, and AI agents. Ask away!

By continuing with the AI assistant, I agree to the site’s terms of use and privacy policy.

AI assistant may make mistakes in responses