“Web design is responsive design. Responsive web design is web design, done right.”
— Andy Clarke, creative director, product & website designer
Responsive web design has been around as a user interface (UI) design approach for a while now. More and more people are therefore looking for a responsive website or a responsive online presence to conduct their businesses. And with its growth, CSS Media Query Breakpoints have become a familiar name in programming and development.
The term “responsive design,” coined by Ethan Marcotte, describes using fluid grids, fluid images, and media queries to create responsive content. In fact, media query breakpoints let designers create adaptive and responsive designs that will automatically adapt to the browser space to ensure content consistency across devices. Media query introduced breakpoints for the sole purpose of this, and designers implement breakpoints in distinctive styles throughout the framework they’re working with.
In this article, we’ll try to walk you through the path of media query breakpoints that you might wanna be familiar with before opting for a new web dev project or if you are one of us who needs to know their websites or online presence thoroughly.
About Media Query
Media query is a CSS technique to design responsive content to be presentable on all devices and screens ranging from desktop to mobile. It essentially includes conditions, and the result will be responsive only if the conditions are met. Also, it lets you apply CSS styles depending on a device’s general type or other characteristics like screen resolution or browser viewport width.
Developers tailor Media-dependent style sheets for different media types ad it consists of a media type and zero or more expression that check for the conditions of particular media features such as, ‘width’, ‘height’, and ‘color’ to tailor presentations to a specific range of output devices without changing the content.
The simplest media query syntax looks like this:
@media media-type and (media-feature-rule) {
/* CSS rules go here */
}
And it consists of the following:
- A media type telling the browser about the kind of media type the code is for
- A media expression, that can be a rule or test to be passed for the contained CSS to be applied
- A set of CSS rules is to be applied if the test passes and the media type is correct.
Also, the possible types of media to specify are all, print and screen. After specifying the type, you can target media features with a media rule. As media features describe the specific characteristics of a given user agent, output device, or environment, they are range features, meaning you can prefix them with ‘min-’ or ‘max-’ to express the minimum or the maximum condition constraints.
Brief on min-width and max-width
The feature detected most often to create responsive designs is viewport width. You can apply CSS if the viewport is above, below, or an exact width, using the min-width, max-width, and width media features.
You can use these features to create responsive layouts for different screen sizes. As aforementioned, the width and height media features can be used as ranges and be prefixed with min- or max- to indicate the measurement of values. Since it’s more useful to use min-width or max-width to create responsive designs, width, and height are rarely found to be used alone.
Min-width is the minimum width of a specific viewport, and the simplest code looks like this:
@media screen and (min-width: 600px) {
p {
font-size: 16px;
}
}
The code is specified for when the minimum screen width is 600px or wider. In this case, it’ll resize the fonts to 16px. Any viewport with this screen width will display the paragraph text in the specified size.
Similarly, with max-width, the code looks like this:
@media screen and (max-width: 700px) {
p {
font-size: 25px;
}
}
In this case, the above code states the alteration of the paragraph’s font size to 25px when the viewport width is 700px or less.
About Breakpoints
Breakpoints are the predefined points in the code, to which the designed contents respond to adapt to the new viewport size or the device type to display the accurate layout. Media query breakpoints are values for a designer to define in the CSS and are decided either based on the device type or the content type.
These breakpoints are referred to as media query breakpoints since they are implemented with a media query. With breakpoints in place, website contents will align themselves with screen size and display themselves in a way that facilitates visual consumption.
Framework-based Implementation
Deciding on an approach to add breakpoints can be tricky as there’s no rule or syntax that’s applicable to all frameworks. Each framework implements these breakpoints in different ways. No two do it the same way, and therefore, different ways to implement breakpoints in different frameworks are briefly described below:
Breakpoints in Bootstrap
As breakpoints are the building blocks of responsive design, Bootstrap has a very distinct and straightforward approach to implementing breakpoints. Its CSS aims to apply the bare minimum of styles to make the layout work better at the smallest breakpoints and then layers on styles to adjust the design for larger viewports.
Bootstrap includes six default breakpoints which are referred to as ‘grid tiers’ sometimes to build responsive designs. These breakpoints can be customized if you’re using the source Sass files. The default Bootstrap breakpoints are as such:
Breakpoint | Class infix | Dimensions |
---|---|---|
X-Small | None | <576px |
Small | sm | ≥576px |
Medium | md | ≥768px |
Large | lg | ≥992px |
Extra large | xl | ≥1200px |
Extra extra large | xxl | ≥1400px |
The breakpoints are customizable with Sass, which can be found in a Sass map in Bootstrap’s official _variables.scss stylesheet. You can use the breakpoints in your code as below:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
Configuring Min-Width in Bootstrap
Bootstrap primarily uses the following breakpoints for layout, grid system, and components:
// Source mixins
// No media query necessary for xs breakpoint as it's effectively
`@media (min-width: 0) { ... }`
@include media-breakpoint-up(sm) { ... }
@include media-breakpoint-up(md) { ... }
@include media-breakpoint-up(lg) { ... }
@include media-breakpoint-up(xl) { ... }
@include media-breakpoint-up(xxl) { ... }
// Usage
// Example: Hide starting at `min-width: 0`, and then show at the `sm` breakpoint
.custom-class {
display: none;
}
@include media-breakpoint-up(sm) {
.custom-class {
display: block;
}
}
These Sass mixins use the values declared in the Sass variables to translate in the compiled CSS. for instance:
// X-Small devices (portrait phones, less than 576px)
// No media query for `xs` since this is the default in Bootstrap
// Small devices (landscape phones, 576px and up)
@media (min-width: 576px) { ... }
// Medium devices (tablets, 768px and up)
@media (min-width: 768px) { ... }
// Large devices (desktops, 992px and up)
@media (min-width: 992px) { ... }
// X-Large devices (large desktops, 1200px and up)
@media (min-width: 1200px) { ... }
// XX-Large devices (larger desktops, 1400px and up)
@media (min-width: 1400px) { ... }
Configuring Max-width in Bootstrap
Sometimes media queries are used in Bootstrap to go in the other direction (the given screen size or smaller):
// No media query necessary for xs breakpoint as it's effectively `@media (max-width: 0) { ... }`
@include media-breakpoint-down(sm) { ... }
@include media-breakpoint-down(md) { ... }
@include media-breakpoint-down(lg) { ... }
@include media-breakpoint-down(xl) { ... }
@include media-breakpoint-down(xxl) { ... }
// Example: Style from medium breakpoint and down
@include media-breakpoint-down(md) {
.custom-class {
display: block;
}
}
Since browsers don’t support range context queries, Bootstrap works around the min- and max- prefixes, and viewports with fractional widths by using values with higher precision. These mixins above subtract .02px from the declared breakpoints and use them as the max-width values. For instance:
// X-Small devices (portrait phones, less than 576px)
@media (max-width: 575.98px) { ... }
// Small devices (landscape phones, less than 768px)
@media (max-width: 767.98px) { ... }
// Medium devices (tablets, less than 992px)
@media (max-width: 991.98px) { ... }
// Large devices (desktops, less than 1200px)
@media (max-width: 1199.98px) { ... }
// X-Large devices (large desktops, less than 1400px)
@media (max-width: 1399.98px) { ... }
// XX-Large devices (larger desktops)
// No media query since the xxl breakpoint has no upper bound on its width
Configuring for Single Breakpoint
If you need to target a single segment of screen sizes, you might want to use the predefined media queries and mixins by Bootstrap. Those are as follows:
@include media-breakpoint-only(xs) { ... }
@include media-breakpoint-only(sm) { ... }
@include media-breakpoint-only(md) { ... }
@include media-breakpoint-only(lg) { ... }
@include media-breakpoint-only(xl) { ... }
@include media-breakpoint-only(xxl) { ... }
And, for instance, if you use the @include media-breakpoint-only(md) { … }, it will result in:
@media (min-width: 768px) and (max-width: 991.98px) { ... }
Between Breakpoints
Moreover, media queries may span multiple breakpoint widths, like:
@include media-breakpoint-between(md, xl) { ... }
Which then results in:
// Example
// Apply styles starting from medium devices and up to extra large devices
@media (min-width: 768px) and (max-width: 1199.98px) { ... }
Pro Tip: customize and extend bootstrap to have more break points!
You can use Sass variables and mixins to add custom and modified breakpoints according to your needs if you’re using the source codes of Bootstrap. As you know, variables and maps determine the number of columns, the width of gutters, and the media query points. You can use them to generate custom mixins as described below:
// Creates a wrapper for a series of columns
@include make-row();
// Make the element grid-ready (applying everything but the width)
@include make-col-ready();
// Without optional size values, the mixin will create equal columns (similar to using .col)
@include make-col();
@include make-col($size, $columns: $grid-columns);
// Offset with margins
@include make-col-offset($size, $columns: $grid-columns);
These mixins allow you to customize the predefined classes in your code and customize them according to your needs. The use case syntax looks as follows:
.example-container {
@include make-container();
// Make sure to define this width after the mixin to override
// `width: 100%` generated by `make-container()`
width: 800px;
}
.example-row {
@include make-row();
}
.example-content-main {
@include make-col-ready();
@include media-breakpoint-up(sm) {
@include make-col(6);
}
@include media-breakpoint-up(lg) {
@include make-col(8);
}
}
.example-content-secondary {
@include make-col-ready();
@include media-breakpoint-up(sm) {
@include make-col(6);
}
@include media-breakpoint-up(lg) {
@include make-col(4);
}
}
Implementing in Bootstrap:
See the Pen Bootstrap breakpoints by Rafia (@rafia2411) on CodePen.
Breakpoints in Tailwind CSS
Breakpoints target the most common screen sizes most people stick to the default one and the creators of Tailwind CSS put a lot of thought into the default breakpoints. We’re trying to explain and exemplify ways of modifying the default ones.
It’s to remember that the order of the breakpoints is crucial, as the framework reads the breakpoint’s order to create necessary media queries. Because of the nature of CSS, the last breakpoint has more specificity than the first breakpoint.
Let’s see the ways of implementing breakpoints in Tailwind CSS:
Configuring to Add a lower breakpoint
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
theme: {
screens: {
xs: "375px",
...defaultTheme.screens
},
}
}
To add an additional small breakpoint, you can use ‘extend’ as the small breakpoint would be added to the end of the breakpoint list, and breakpoints need to be sorted in ascending order to work as expected with a min-width breakpoint system.
Configuring to Add A Bigger Breakpoint
In the extended section
You can easily add an additional breakpoint with the ‘extend’ key if you need to, and the code will look like this:
module.exports = {
theme: {
extend: {
screens: {
'3xl': '1600px',
},
},
},
plugins: [],
}
This will enable you to add your custom screen to the end of the default breakpoint list.
By overwriting the defaults
You can override the entire ‘screens’ by respecifying the default breakpoints:
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
theme: {
screens: {
'xs': '475px',
...defaultTheme.screens,
},
},
plugins: [],
}
The default theme is exposed at ‘tailwindcss/defaultTheme’ so that you don’t have to maintain the list of default breakpoints.
Configuring Using Custom Screen Names
Max-width Breakpoints
You can specify your screens as objects with a ‘max’ key to work with max-width breakpoints. The syntax should look like this:
module.exports = {
theme: {
screens: {
'2xl': {'max': '1535px'},
// => @media (max-width: 1535px) { ... }
'xl': {'max': '1279px'},
// => @media (max-width: 1279px) { ... }
'lg': {'max': '1023px'},
// => @media (max-width: 1023px) { ... }
'md': {'max': '767px'},
// => @media (max-width: 767px) { ... }
'sm': {'max': '639px'},
// => @media (max-width: 639px) { ... }
}
}
}
Remember to list max-width breakpoints in descending order for them to override each other as expected.
Fixed-range breakpoints
If you want to specify both a ‘min-width’ and ‘max-width’ in your breakpoints, you can use ‘min’ and ‘max’ keys together. The syntax will look like this:
module.exports = {
theme: {
screens: {
'sm': {'min': '640px', 'max': '767px'},
// => @media (min-width: 640px and max-width: 767px) { ... }
'md': {'min': '768px', 'max': '1023px'},
// => @media (min-width: 768px and max-width: 1023px) { ... }
'lg': {'min': '1024px', 'max': '1279px'},
// => @media (min-width: 1024px and max-width: 1279px) { ... }
'xl': {'min': '1280px', 'max': '1535px'},
// => @media (min-width: 1280px and max-width: 1535px) { ... }
'2xl': {'min': '1536px'},
// => @media (min-width: 1536px) { ... }
},
}
}
These irregular breakpoints will only be effective when the viewport size is explicitly within the defined range. The code will look like this:
<div class="md:text-center">
This text will be centered on medium screens, but revert back
to the default (left-aligned) at all other screen sizes.
</div>
Multi-range breakpoints
You can also have a single breakpoint definition to apply in multiple ranges. For instance, if you want your breakpoints to base on the content area, rather than the entire viewport, you’ll be able to simulate that by having one of your breakpoints fall back to a smaller breakpoint when the sidebar becomes visible and shrinks to the content area.
A simple example is given below for a better understanding:
module.exports = {
theme: {
screens: {
'sm': '500px',
'md': [
// Sidebar appears at 768px, so revert to `sm:` styles between 768px
// and 868px, after which the main content area is wide enough again to
// apply the `md:` styles.
{'min': '668px', 'max': '767px'},
{'min': '868px'}
],
'lg': '1100px',
'xl': '1400px',
}
}
}
Custom media queries
Moreover, if you want to have full granted control over the generated media query, you might want to use the ‘raw’ key. The syntax will be as follows:
module.exports = {
theme: {
extend: {
screens: {
'tall': { 'raw': '(min-height: 800px)' },
// => @media (min-height: 800px) { ... }
}
}
}
}
The ‘min’ and ‘max’ keys will be ignored and the output will be as-is if the media queries are defined using the ‘raw’ key.
Implementing Breakpoints in Tailwind CSS
See the Pen Tailwind breakpoints by Rafia (@rafia2411) on CodePen.
Breakpoints in Foundation
Foundation has three core breakpoints for sites:
- Small: any screen.
- Medium: any screen 640 pixels or larger.
- Large: any screen 1024 pixels or larger.
You can modify the components at different screen sizes using special breakpoint classes, unlike Bootstrap or Tailwind CSS. See the code exemplified below:
<div class="grid-x grid-margin-x">
<div class="cell small-6 medium-4"></div>
<div class="cell small-6 medium-8"></div>
</div>
In the above code, the left-hand column is six columns wide on small screens, hence .small-6. On medium-sized screens, the class .medium-4 overrides the small style, changing the column to be four wide.
If you’re using the CSS version, you can use the following media queries to imitate the core three:
/* Small only */
@media screen and (max-width: 39.9375em) {}
/* Medium and up */
@media screen and (min-width: 40em) {}
/* Medium only */
@media screen and (min-width: 40em) and (max-width: 63.9375em) {}
/* Large and up */
@media screen and (min-width: 64em) {}
/* Large only */
@media screen and (min-width: 64em) and (max-width: 74.9375em) {}
Changing the Breakpoints
You can change the default breakpoints if you’re using the Sass files. The names of the breakpoints and their widths are enlisted in the official doc as such:
$breakpoints: (
small: 0px,
medium: 640px,
large: 1024px,
xlarge: 1200px,
xxlarge: 1440px,
);
These values are converted to ems at the end for use in media queries though they’re listed above in pixels. Also, there are two extra breakpoints (xlarge & xxlarge) that are not used for any components and do not output any CSS classes that use them by default.
Remember to list the breakpoints in ascending order so that the keys like ‘down’ in the breakpoint function will work as expected.
You can also change it by modifying the $breakpoint-classes variables in your settings file and any change in the list will change the CSS class output. It will look like this:
$breakpoint-classes: (small medium large);
To add xlarge class in your CSS, you can just add it to the end of the list as such:
$breakpoint-classes: (small medium large xlarge);
Sass
The Breakpoint Mixin
According to their official doc, you can use the named breakpoints, or custom pixel, rem, or em values. You’ll have to call it with @include and include the CSS content you want inside 2nd brackets. It should look as follows:
.element {
// Only affects medium screens and larger
@include breakpoint(medium) {
// All CSS in here goes inside the media query
}
}
After separating the breakpoint value by space, adding keywords can change the media query behavior.
.element {
// Only affects medium screens and smaller
@include breakpoint(medium down) { }
// Only affects medium screens, not small or large
@include breakpoint(medium only) { }
}
You can also pass in custom values of your choice since all values are converted to em at the end.
Check the example below:
.element {
// Converted to 20em
@include breakpoint(320px) { }
// Unitless values are assumed to be pixels
@include breakpoint(320) { }
// Converted to 40em
@include breakpoint(40rem) { }
}
Lastly, there are three special media, portrait, landscape, and retina that are not width-based. Doing so, you’ll get the output of a media query for device orientation or pixel density rather than the screen width. The configuration should be as follows:
.element {
@include breakpoint(landscape) {
// CSS for landscape-oriented devices only
}
@include breakpoint(retina) {
// CSS for high-resolution displays only
}
}
Breakpoint Function
The functionality of the breakpoint() mixin comes from an internal function similarly named breakpoint(). While writing your own media query, you can use this function to directly access the logic of the mixin. See the example below:
@media screen and #{breakpoint(medium)} {
// Medium and up styles
}
You can use this to combine media queries together like:
@media screen and #{breakpoint(medium)} and #{breakpoint(xlarge down)} {
// Medium to extra large styles
}
JavaScript
Working with Media Queries
Foundation doc includes a set of helpful functionalities in their JavaScript. You can find them all on the Foundation.MediaQuery object.
As the MediaQuery utility uses the Sass breakpoint settings and requires the Foundation CSS to be imported, you’d better remember to include either foundation-everything() or foundation-global-styles().
You can get the name of the current breakpoint with MediaQuery.current.
Foundation.MediaQuery.current // => 'small', 'medium', etc.
Also, you can use MediaQuery.is() to check where the breakpoint of the screen is at, such as:
Foundation.MediaQuery.is('medium') // => True for "medium" or larger
You can use modifiers like up(default), down, and only in Sass or use the equivalent MediaQuery.atLeast(), MediaQuery.only() and MediaQuery.upTo() like:
// ↑ True for "medium" or larger (by default)
Foundation.MediaQuery.is('medium up');
Foundation.MediaQuery.atLeast('medium');
// → True for "medium" only
Foundation.MediaQuery.is('medium only');
Foundation.MediaQuery.only('medium');
// ↓ True for "medium" or smaller
Foundation.MediaQuery.is('medium down');
Foundation.MediaQuery.upTo('medium');
If you need to get the media query breakpoint, use MediaQuery.get like this:
Foundation.MediaQuery.get('medium') // => only screen and (min-width: 640px)
Implementing Breakpoints in Foundation
See the Pen Foundation breakpoints by Rafia (@rafia2411) on CodePen.
Adding CSS Breakpoints: Useful Tips!
You might want to consider the following approaches before deciding on the breakpoints you’re to apply in your design to create better output and responsiveness:
- Using minified HTML, CSS, and JavaScript to optimize your code and reduce page load time (including deleting spaces, commas, and other redundant characters).
- Setting the priorities right by starting from smaller viewports is more complicated to design for bigger screens or viewports than it is to do it for smaller viewports.
- First addressing the mobile view while designing the output then tweaking it for the desktop view. Doing so, the block-level elements will automatically expand to 100% and most of the contents will be optimized for mobile view.
- You should prioritize the features based on the type & form factor of the device.
Using media queries is a popular way to deliver a tailored style sheet into a website to set the conditions for the design to adapt to the size of the screen. Now that you are familiar with the implementation techniques of these breakpoints, hopefully, you’ll get into a better design approach. Though it’s ideal, it’s not always the best approach to do so. To create the best result, think about content at every size, and fix the littlest quirks there are with custom media queries; thus you’ll be investing in the future of your website and in the future of the web in general.