← Back to Articles

Advanced CSS: Units & Layout

CSS Units Comparison

/* Absolute units */
px   /* 1 pixel */
pt   /* 1 point = 1/72 inch */

/* Relative to parent */
em   /* 1em = parent's font-size */
%    /* Percentage of parent */

/* Relative to root */
rem  /* 1rem = root (html) font-size */

/* Viewport relative */
vw   /* 1vw = 1% of viewport width */
vh   /* 1vh = 1% of viewport height */
vmin /* 1vmin = 1% of smaller dimension */
vmax /* 1vmax = 1% of larger dimension */

/* Examples */
.element {
    font-size: 1rem;      /* 16px if root is 16px */
    padding: 1em;         /* Equals current font-size */
    width: 50%;           /* 50% of parent */
    height: 100vh;        /* Full viewport height */
}

rem vs em

/* rem - consistent, predictable */
html { font-size: 16px; }
.button {
    font-size: 1rem;    /* Always 16px */
    padding: 0.5rem 1rem; /* Always 8px 16px */
}

/* em - contextual, component-relative */
.card {
    font-size: 1rem;
    padding: 1em;       /* 16px (equals font-size) */
}
.card .button {
    font-size: 0.875em; /* 14px (87.5% of 16px) */
    margin: 0.5em;      /* 7px (0.5 * 14px) */
}

/* Best practice: rem for layout, em for components */
body { font-size: 1rem; }
.component { padding: 1em; } /* Scales with component */

Fluid Typography with clamp()

/* clamp(min, preferred, max) */
h1 {
    font-size: clamp(1.5rem, 4vw, 3rem);
    /* Min: 24px, Preferred: 4vw, Max: 48px */
}

/* Fluid spacing */
.container {
    padding: clamp(1rem, 3vw, 2rem);
    max-width: min(100% - 2rem, 1200px);
}

/* Complete fluid type scale */
:root {
    --fluid-min: 1rem;
    --fluid-max: 2.5rem;
    --fluid-ratio: 1.25;
}

h1 { font-size: clamp(var(--fluid-min), 5vw, var(--fluid-max)); }
h2 { font-size: clamp(var(--fluid-min), 4vw, 2rem); }
p { font-size: clamp(0.875rem, 2vw, 1.125rem); }

CSS Math Functions

/* calc() - calculations */
.element {
    width: calc(100% - 2rem);
    margin-left: calc(50% - 300px);
}

/* min() - smallest value */
.container {
    width: min(100%, 1200px);
    padding: min(5vw, 2rem);
}

/* max() - largest value */
.sidebar {
    width: max(200px, 20%);
}

/* Combine functions */
.card {
    width: calc(min(100%, 400px) - 2rem);
    font-size: clamp(1rem, 2vw, max(1.125rem, 2vw));
}

Container Queries

/* Define container */
.card-container {
    container-type: inline-size;
    container-name: card;
}

/* Query container size (not viewport) */
@container card (min-width: 400px) {
    .card {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }
}

@container card (min-width: 600px) {
    .card {
        grid-template-columns: 1fr 1fr 1fr;
    }
}

/* Container query units */
@container card (min-width: 30cqw) {
    /* cqw = container query width */
}

Modern Responsive Patterns

/* Responsive grid */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
}

/* Responsive flex */
.flex {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.flex > * {
    flex: 1 1 300px; /* Grow, shrink, basis */
}

/* Aspect ratio */
.video {
    aspect-ratio: 16 / 9;
    width: 100%;
}

/* Responsive images */
img {
    max-width: 100%;
    height: auto;
    object-fit: cover;
}

Subgrid

/* Parent grid */
.parent {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

/* Child uses parent's grid */
.child {
    display: grid;
    grid-template-columns: subgrid;
    grid-column: span 2;
}

Key Takeaways

  • Use rem for consistent sizing
  • Use em for component-relative sizing
  • Use clamp() for fluid typography
  • Use container queries for component responsiveness
  • Use min()/max() for constraints

Next Steps

Continue to professional skills: