DEV Community

Deepika Pusala
Deepika Pusala

Posted on

Day-5 as Full Stack Intern: Media Queries & Fluid Typography

1. Mobile-First Media Queries

What is a Media Query?

A media query is a CSS feature that allows us to apply different CSS styles based on the conditions of the device or viewport.

In simple words:

"If this condition is true, apply these CSS rules."

For example:

@media (min-width: 768px) {
    .container {
        display: flex;
    }
}
Enter fullscreen mode Exit fullscreen mode

This means:

If the viewport width is 768px or greater, apply the styles inside the media query.

Media queries are mainly used to create responsive websites that adapt to different screen sizes such as mobile phones, tablets, laptops, and desktops.


What is Responsive Web Design?

A responsive website automatically adapts its layout and appearance according to the available screen size.

For example:

Mobile:

[ Card 1 ]
[ Card 2 ]
[ Card 3 ]
Enter fullscreen mode Exit fullscreen mode

Desktop:

[ Card 1 ] [ Card 2 ] [ Card 3 ]
Enter fullscreen mode Exit fullscreen mode

The same website can use different layouts depending on the viewport size.


Basic Syntax of a Media Query

@media media-type and (condition) {
    /* CSS rules */
}
Enter fullscreen mode Exit fullscreen mode

Example:

@media screen and (max-width: 600px) {
    body {
        background: lightblue;
    }
}
Enter fullscreen mode Exit fullscreen mode

There are three important parts:

@media
   ↓
media type
   ↓
condition
   ↓
CSS rules
Enter fullscreen mode Exit fullscreen mode

However, the media type is optional, so this is also very common:

@media (max-width: 600px) {
    body {
        background: lightblue;
    }
}
Enter fullscreen mode Exit fullscreen mode

Media Types

A media type specifies the type of output device or presentation.

1. screen

Used for screens such as:

  • Mobile phones
  • Tablets
  • Laptops
  • Desktop monitors

Example:

@media screen and (max-width: 600px) {
    body {
        font-size: 14px;
    }
}
Enter fullscreen mode Exit fullscreen mode

2. print

Used when the webpage is being printed or viewed in print preview.

For example, we may want to hide navigation when printing:

@media print {
    nav {
        display: none;
    }
}
Enter fullscreen mode Exit fullscreen mode

3. speech

Used for speech-based presentation, such as speech synthesizers and screen-reading technologies.

@media speech {
    /* speech-related styles */
}
Enter fullscreen mode Exit fullscreen mode

This is less commonly used in everyday responsive development.

4. all

Represents all media types.

@media all {
    /* styles */
}
Enter fullscreen mode Exit fullscreen mode

In normal responsive development, we usually don't need to explicitly write all.


Important Media Features

Media queries can check many different conditions.

The most commonly used ones are:

min-width
max-width
min-height
max-height
orientation
prefers-color-scheme
hover
pointer
resolution
Enter fullscreen mode Exit fullscreen mode

min-width

min-width means:

"The viewport width must be greater than or equal to this value."

Example:

@media (min-width: 768px) {
    .container {
        display: flex;
    }
}
Enter fullscreen mode Exit fullscreen mode

This applies when:

768px or more → YES
767px or less → NO
Enter fullscreen mode Exit fullscreen mode

Think of it as:

width >= 768px
Enter fullscreen mode Exit fullscreen mode

max-width

max-width means:

"The viewport width must be less than or equal to this value."

Example:

@media (max-width: 768px) {
    .container {
        padding: 10px;
    }
}
Enter fullscreen mode Exit fullscreen mode

This applies when:

768px or less → YES
769px or more → NO
Enter fullscreen mode Exit fullscreen mode

Think of it as:

width <= 768px
Enter fullscreen mode Exit fullscreen mode

What is Mobile-First Design?

Mobile-first design means we first write the default CSS for smaller screens and then progressively add styles for larger screens.

The basic pattern is:

/* Mobile / default styles */

.container {
    display: block;
}

/* Larger screens */

@media (min-width: 768px) {
    .container {
        display: flex;
    }
}
Enter fullscreen mode Exit fullscreen mode

The idea is:

Mobile
  ↓
Base CSS
  ↓
Tablet / larger screen
  ↓
min-width
  ↓
Desktop
Enter fullscreen mode Exit fullscreen mode

So mobile-first development generally uses min-width media queries.


Example of Mobile-First Design

Suppose we have three cards.

On mobile, we want them stacked:

.container {
    display: flex;
    flex-direction: column;
    gap: 20px;
}
Enter fullscreen mode Exit fullscreen mode

On larger screens, we want them in a row:

@media (min-width: 768px) {
    .container {
        flex-direction: row;
    }
}
Enter fullscreen mode Exit fullscreen mode

The result is:

Mobile:

[ Card 1 ]
[ Card 2 ]
[ Card 3 ]
Enter fullscreen mode Exit fullscreen mode

Larger screen:

[ Card 1 ] [ Card 2 ] [ Card 3 ]
Enter fullscreen mode Exit fullscreen mode

Why Mobile-First?

Mobile-first design starts with the smallest and simplest layout and progressively enhances it for larger screens.

Advantages include:

  • Better mobile experience
  • Simpler base CSS
  • Easier responsive design
  • Less unnecessary CSS
  • Works well with modern responsive development

Instead of starting with a complicated desktop layout and trying to remove things for mobile, we start simple and add features as more space becomes available.


min-width vs max-width

Mobile-first

/* Default = mobile */

.card {
    width: 100%;
}

@media (min-width: 768px) {
    .card {
        width: 50%;
    }
}
Enter fullscreen mode Exit fullscreen mode

The direction is:

Small → Large
Enter fullscreen mode Exit fullscreen mode

Desktop-first

/* Default = desktop */

.card {
    width: 25%;
}

@media (max-width: 768px) {
    .card {
        width: 100%;
    }
}
Enter fullscreen mode Exit fullscreen mode

The direction is:

Large → Small
Enter fullscreen mode Exit fullscreen mode

Both approaches are valid, but mobile-first is a very common and useful approach for responsive websites.


and

The and operator means both conditions must be true.

Example:

@media (min-width: 768px) and (max-width: 1200px) {
    .container {
        padding: 30px;
    }
}
Enter fullscreen mode Exit fullscreen mode

This means:

width >= 768px
AND
width <= 1200px
Enter fullscreen mode Exit fullscreen mode

So:

700px   → ❌
768px   → ✅
900px   → ✅
1200px  → ✅
1300px  → ❌
Enter fullscreen mode Exit fullscreen mode

Using Multiple Conditions with ,

A comma acts like OR between media queries.

Example:

@media (max-width: 600px), (orientation: portrait) {
    .container {
        padding: 10px;
    }
}
Enter fullscreen mode Exit fullscreen mode

This means the styles apply if:

width <= 600px
OR
orientation is portrait
Enter fullscreen mode Exit fullscreen mode

If either condition is true, the styles can apply.


not

The not keyword negates a media query.

For example:

@media not print {
    /* styles */
}
Enter fullscreen mode Exit fullscreen mode

This means the styles apply when the presentation is not print.

not is useful to know, but in everyday responsive development, min-width and max-width are used much more frequently.


orientation

The orientation feature checks whether the viewport is portrait or landscape.

Portrait

@media (orientation: portrait) {
    .container {
        padding: 10px;
    }
}
Enter fullscreen mode Exit fullscreen mode

Portrait generally means the viewport is taller than it is wide.

┌──────────┐
│          │
│          │
│          │
│          │
└──────────┘
Enter fullscreen mode Exit fullscreen mode

Landscape

@media (orientation: landscape) {
    .container {
        padding: 30px;
    }
}
Enter fullscreen mode Exit fullscreen mode

Landscape generally means the viewport is wider than it is tall.

┌──────────────────┐
│                  │
│                  │
└──────────────────┘
Enter fullscreen mode Exit fullscreen mode

Other Useful Media Features

prefers-color-scheme

Detects whether the user prefers a light or dark color scheme.

@media (prefers-color-scheme: dark) {
    body {
        background: black;
        color: white;
    }
}
Enter fullscreen mode Exit fullscreen mode

hover

Checks whether the user's primary input device supports hovering.

@media (hover: hover) {
    button:hover {
        transform: scale(1.05);
    }
}
Enter fullscreen mode Exit fullscreen mode

pointer

Can be used to detect pointer characteristics.

@media (pointer: coarse) {
    button {
        padding: 20px;
    }
}
Enter fullscreen mode Exit fullscreen mode

This can be useful for touch-based interfaces where larger controls are easier to use.


Media Queries Are Not Only for Width

Media queries can change almost any CSS property.

For example:

h1 {
    font-size: 2rem;
}

@media (min-width: 768px) {
    h1 {
        font-size: 3rem;
    }
}
Enter fullscreen mode Exit fullscreen mode

You can also change:

display
flex-direction
grid columns
font-size
padding
margin
width
height
gap
visibility
position
and many other CSS properties
Enter fullscreen mode Exit fullscreen mode

Important Rule About Breakpoints

Do not blindly memorize:

768px = tablet
1024px = laptop
1200px = desktop
Enter fullscreen mode Exit fullscreen mode

These are commonly used values, but they are not strict device definitions.

Choose breakpoints based on when your layout actually needs to change.

For example, if your cards become too cramped at 850px, you might use:

@media (min-width: 850px) {
    /* layout changes */
}
Enter fullscreen mode Exit fullscreen mode

The design should determine the breakpoint.


Simple Mental Model for Media Queries

Think of a media query like a CSS if statement:

IF condition is true
        ↓
apply these CSS rules
Enter fullscreen mode Exit fullscreen mode

For example:

@media (min-width: 768px) {
    .container {
        display: flex;
    }
}
Enter fullscreen mode Exit fullscreen mode

Means:

IF viewport width >= 768px
        ↓
make .container a flex container
Enter fullscreen mode Exit fullscreen mode

2. Fluid Typography

Fluid typography means creating text whose size can smoothly grow or shrink according to the viewport size.

Traditional responsive typography might look like this:

h1 {
    font-size: 32px;
}

@media (min-width: 768px) {
    h1 {
        font-size: 48px;
}
Enter fullscreen mode Exit fullscreen mode

This creates fixed steps:

Mobile → 32px
Desktop → 48px
Enter fullscreen mode Exit fullscreen mode

Fluid typography allows the size to change gradually:

32px
 ↓
34px
 ↓
36px
 ↓
39px
 ↓
42px
 ↓
45px
 ↓
48px
Enter fullscreen mode Exit fullscreen mode

The main CSS concepts used for fluid typography are:

rem
vw
clamp()
Enter fullscreen mode Exit fullscreen mode

rem

rem stands for root em.

It is relative to the font size of the root <html> element.

Browsers commonly use:

html {
    font-size: 16px;
}
Enter fullscreen mode Exit fullscreen mode

Therefore:

1rem = 16px
2rem = 32px
3rem = 48px
4rem = 64px
Enter fullscreen mode Exit fullscreen mode

Example:

h1 {
    font-size: 3rem;
}
Enter fullscreen mode Exit fullscreen mode

With a 16px root font size:

3rem = 48px
Enter fullscreen mode Exit fullscreen mode

Why Use rem?

rem provides scalable and consistent sizing.

For example:

body {
    font-size: 1rem;
}

h1 {
    font-size: 3rem;
}

p {
    font-size: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Instead of hardcoding every value in pixels, the sizes are based on the root font size.

rem is especially useful for:

  • Typography
  • Spacing
  • Scalable layouts
  • Accessibility-friendly sizing

vw

vw means viewport width.

1vw = 1% of the viewport width
Enter fullscreen mode Exit fullscreen mode

For example, if the viewport width is:

1000px
Enter fullscreen mode Exit fullscreen mode

then:

1vw = 10px
Enter fullscreen mode Exit fullscreen mode

If the viewport width is:

500px
Enter fullscreen mode Exit fullscreen mode

then:

1vw = 5px
Enter fullscreen mode Exit fullscreen mode

Therefore, vw naturally changes when the viewport width changes.


Example of vw

h1 {
    font-size: 5vw;
}
Enter fullscreen mode Exit fullscreen mode

The font size changes according to the viewport width.

However, using only vw can be problematic.

On a very small screen, the font may become too small.

On a very large screen, it may become extremely large.

For example:

Small screen
5vw → potentially too small

Huge screen
5vw → potentially too large
Enter fullscreen mode Exit fullscreen mode

This is why clamp() is extremely useful.


clamp()

clamp() allows us to define a minimum value, preferred value, and maximum value.

The syntax is:

clamp(minimum, preferred, maximum)
Enter fullscreen mode Exit fullscreen mode

Example:

h1 {
    font-size: clamp(2rem, 5vw, 4rem);
}
Enter fullscreen mode Exit fullscreen mode

This means:

Minimum  → 2rem
Preferred → 5vw
Maximum  → 4rem
Enter fullscreen mode Exit fullscreen mode

In simple words:

Let the font size scale according to 5vw, but never let it become smaller than 2rem or larger than 4rem.


How clamp() Works

Suppose:

h1 {
    font-size: clamp(2rem, 5vw, 4rem);
}
Enter fullscreen mode Exit fullscreen mode

Assuming:

1rem = 16px
Enter fullscreen mode Exit fullscreen mode

we have:

2rem = 32px
4rem = 64px
Enter fullscreen mode Exit fullscreen mode

So the range is:

Minimum = 32px
Maximum = 64px
Enter fullscreen mode Exit fullscreen mode

Now imagine different viewport sizes.

Small viewport

5vw = 16px
Enter fullscreen mode Exit fullscreen mode

But the minimum is 32px.

Therefore:

font-size = 32px
Enter fullscreen mode Exit fullscreen mode

Medium viewport

5vw = 40px
Enter fullscreen mode Exit fullscreen mode

40px is within the allowed range.

Therefore:

font-size = 40px
Enter fullscreen mode Exit fullscreen mode

Large viewport

5vw = 60px
Enter fullscreen mode Exit fullscreen mode

60px is still within the allowed range.

Therefore:

font-size = 60px
Enter fullscreen mode Exit fullscreen mode

Very large viewport

5vw = 100px
Enter fullscreen mode Exit fullscreen mode

But the maximum is 64px.

Therefore:

font-size = 64px
Enter fullscreen mode Exit fullscreen mode

So the result is approximately:

Viewport       Font Size

Small          32px  ← minimum
Medium         40px
Large          60px
Very Large     64px  ← maximum
Enter fullscreen mode Exit fullscreen mode

The Three Parts of clamp()

Remember:

clamp(2rem, 5vw, 4rem)
                 
      MIN  IDEAL  MAX
Enter fullscreen mode Exit fullscreen mode

First value → Minimum

2rem
Enter fullscreen mode Exit fullscreen mode

The value should not go below this.

Second value → Preferred

5vw
Enter fullscreen mode Exit fullscreen mode

The value tries to scale fluidly according to the viewport.

Third value → Maximum

4rem
Enter fullscreen mode Exit fullscreen mode

The value should not exceed this.


Why Use clamp() for Typography?

Without clamp(), we might write many media queries:

h1 {
    font-size: 32px;
}

@media (min-width: 600px) {
    h1 {
        font-size: 36px;
    }
}

@media (min-width: 900px) {
    h1 {
        font-size: 42px;
    }
}

@media (min-width: 1200px) {
    h1 {
        font-size: 48px;
    }
}
Enter fullscreen mode Exit fullscreen mode

With clamp():

h1 {
    font-size: clamp(2rem, 5vw, 3rem);
}
Enter fullscreen mode Exit fullscreen mode

The browser can calculate an appropriate size between the minimum and maximum.


Does clamp() Replace Media Queries?

No.

clamp() can reduce the need for media queries when we only need to change a value smoothly.

For example:

h1 {
    font-size: clamp(2rem, 5vw, 4rem);
}
Enter fullscreen mode Exit fullscreen mode

This can replace several typography-specific breakpoints.

However, media queries are still needed when the layout or behavior itself needs to change.

For example:

Mobile:
[ Menu Button ]

Desktop:
[ Home | About | Projects | Contact ]
Enter fullscreen mode Exit fullscreen mode

We still need a media query to change the layout or visibility.

So remember:

clamp()
→ controls a fluid value

media query
→ changes CSS rules based on a condition
Enter fullscreen mode Exit fullscreen mode

rem vs vw vs clamp()

rem

font-size: 2rem;
Enter fullscreen mode Exit fullscreen mode

Means:

Scale relative to the root font size.


vw

font-size: 5vw;
Enter fullscreen mode Exit fullscreen mode

Means:

Scale relative to the viewport width.


clamp()

font-size: clamp(2rem, 5vw, 4rem);
Enter fullscreen mode Exit fullscreen mode

Means:

Scale fluidly using 5vw, but stay between 2rem and 4rem.


Fluid Typography Example

A modern responsive heading could be:

h1 {
    font-size: clamp(2rem, 5vw, 4rem);
}
Enter fullscreen mode Exit fullscreen mode

A paragraph could use:

p {
    font-size: clamp(1rem, 1.5vw, 1.25rem);
}
Enter fullscreen mode Exit fullscreen mode

A section's spacing can also be fluid:

section {
    padding: clamp(1rem, 5vw, 5rem);
}
Enter fullscreen mode Exit fullscreen mode

So clamp() is not limited to fonts. It can be used for many CSS properties that accept suitable numeric values.


Mobile-First + Fluid Typography Together

These two concepts work together very well.

For example:

/* Base/mobile styles */

.hero-title {
    font-size: clamp(2rem, 5vw, 4rem);
}

.container {
    display: grid;
    grid-template-columns: 1fr;
}

/* Larger screens */

@media (min-width: 768px) {
    .container {
        grid-template-columns: 1fr 1fr;
    }
}
Enter fullscreen mode Exit fullscreen mode

Here:

clamp()
→ controls the fluid heading size

media query
→ changes the layout
Enter fullscreen mode Exit fullscreen mode

We don't have to choose between them.


Final Comparison

MEDIA QUERY
↓
"When this condition is true,
 change my CSS rules."

Example:
@media (min-width: 768px)


rem
↓
"Scale relative to the root font size."

Example:
2rem


vw
↓
"Scale relative to the viewport width."

Example:
5vw


clamp()
↓
"Keep a value between a minimum
 and maximum while allowing it
 to scale fluidly."

Example:
clamp(2rem, 5vw, 4rem)
Enter fullscreen mode Exit fullscreen mode

Quick Cheat Sheet

Media Query

@media (min-width: 768px) {
    /* styles */
}
Enter fullscreen mode Exit fullscreen mode

Mobile-first

/* Mobile/default */
.element {
    ...
}

/* Larger screens */
@media (min-width: 768px) {
    .element {
        ...
    }
}
Enter fullscreen mode Exit fullscreen mode

rem

font-size: 2rem;
Enter fullscreen mode Exit fullscreen mode

rem = relative to the root font size.

vw

font-size: 5vw;
Enter fullscreen mode Exit fullscreen mode

vw = 1% of viewport width.

clamp()

font-size: clamp(2rem, 5vw, 4rem);
Enter fullscreen mode Exit fullscreen mode
MINIMUM → PREFERRED → MAXIMUM
   2rem       5vw         4rem
Enter fullscreen mode Exit fullscreen mode

Most important idea:

Media queries decide WHEN CSS rules change. rem and vw provide relative sizing, while clamp() allows a value to scale fluidly within a safe minimum and maximum range.

Top comments (0)