6. Media queries
Media queries let you swap out a page's styles based on certain conditions, such as: the screen width, the pixel density, the device orientation, colors, etc. They are a fundamental part of responsive design, since they let us adapt the layout to different devices and screens.
Syntax
Media queries have their own structure. On one side, the styles are wrapped in an @media, a condition, and {}. Then, inside the braces, you write the styles that will be applied when the condition is met.
@media (condition) {
/* Styles */
}
Let's look at a quick case. We want to apply a red background color when the screen width is less than 600px. We can write:
@media (width < 600px) {
body {
background-color: red;
}
}
{: .advice }
A popular and older alternative is using max-width and min-width. In this case, the following code would be equivalent to the previous one: @media all and (max-width: 600px) { ... }. However, the earlier syntax is more flexible, more modern, and easier to understand.
If in addition we want the background color to be red from 600px wide onwards but green at 600px or less, we can write:
body {
background-color: red;
}
@media (width < 600px) {
body {
background-color: green;
}
}
If we use nesting, we can make the code more compact:
body {
background-color: red;
@media (width < 600px) {
background-color: green;
}
}
We applied a red background color by default, and then we overrode that style with a green color when the screen width is less than 600px. The order of the cascade matters. The media query applies to all the styles found inside it. It is advisable to place it at the end of the CSS file or below the selector it applies to.
Now we'll add another use case. We want to meet the following requirements:
- If the screen width is less than 600px, the background color will be red.
- If the screen width is greater than 600px but less than 1000px, the background color will be green.
- If the screen width is greater than 1000px, the background color will be blue.
We can implement it with the following styles:
/* Default styles: blue */
body {
background-color: blue;
}
/* Styles for screens smaller than 600px: red */
@media (width < 600px) {
body {
background-color: red;
}
}
/* Styles for screens between 600px and 1000px: green */
@media (600px <= width < 1000px) {
body {
background-color: green;
}
}
If we use nesting, it would look like this:
body {
background-color: blue;
@media (width < 600px) {
background-color: red;
}
@media (600px <= width < 1000px) {
background-color: green;
}
}
We set different styles for small, medium, and large screens. You should be aware that every device has a different resolution, although we only care about the width, since the height is infinite (as tall as the page's scroll gets). For example, a second-generation iPhone SE has a resolution of 375px wide, an iPad has a resolution of 810px wide, a 13-inch monitor has an approximate resolution of 1280px wide, an HD monitor has a resolution of 1920px wide, a 4K monitor has a resolution of 3840px wide... and we could keep going. How can we define styles for each of these devices without losing our minds?
Generally, some imaginary lines are drawn and it is assumed that everything falling within a given range is a specific device. You can use the following as a reference:
| Device | Width |
|---|---|
| Smartphone | 0px - 600px |
| Tablet | 600px - 1000px |
| Monitor and TV | 1000px onwards |
{: .advice }
There is no better way to test a website than using real devices, so grab everything you have within reach. The browsers' responsive design views are also a good help (you can enable it by pressing Ctrl + Shift + M in Firefox or Ctrl + Shift + I in Chrome).
Screen
It is possible to add a condition so that the media query distinguishes between screens and printers. To do so, you use the keyword screen or print followed by an and and the condition.
The following media query applies only to screens:
@media screen and (width < 600px) {
body {
background-color: red;
}
}
And the following media query applies only to printers:
@media print and (width < 600px) {
body {
background-color: red;
}
}
It is useful when we want to remove unnecessary elements in the printed version of a web page.
Monochrome
There are devices that are monochromatic, that is, they can only display one color (usually grayscale). Such as e-ink screens, printers, etc.
For them, there is the monochrome condition, which lets you apply styles based on how many colors the device can display.
@media (monochrome) {
body {
background-color: red;
}
}
Use it to adjust the color contrast based on how many colors the device can display.
Orientation
The orientation condition lets you apply styles based on the device's orientation. It can be portrait (vertical) or landscape (horizontal).
@media (orientation: portrait) {
body {
background-color: red;
}
}
Really useful for bringing buttons and navigation elements closer to users' thumbs on devices with vertical screens.
Some helpers
Classes to show elements on specific devices
In any design there are elements we only need to show at specific resolutions or on specific devices. For example, the hamburger button (the name given to the icon with 3 horizontal lines used to open menus), which is only needed on small screens, or the "back to top" button for large screens. That's why we can use small helpers, in the form of classes, to show or hide elements based on the resolution.
You can use the following CSS classes for that purpose:
.is-in-desktop {
display: none;
@media (1000px < width) {
display: inherit;
}
}
.is-in-tablet {
display: none;
@media (600px <= width < 1000px) {
display: inherit;
}
}
.is-in-mobile {
display: none;
@media (width < 600px) {
display: inherit;
}
}
If I want a button to be shown only on mobile devices, I can write:
<button class="is-in-mobile">Open menu</button>
It will hide it on tablet and desktop but not on smartphones.
You can also combine them with each other. For example, if I want a button to be shown on tablet and desktop, but not on mobile, I can write:
<a href="#top" class="is-in-tablet is-in-desktop">Back to top</a>
If you don't add any class, the element will be shown on all devices.
Implementation in Sass
If we work with Sass, we can use a couple of variables and mixins to achieve more semantic styles.
Starting from the following code:
// Smartphones: 0px - 600px
$breakpoint--s: 600px
// Tablets: 600px - 1000px
$breakpoint--m: 1000px
@mixin media ($breakpoint)
@media all and (max-width: $breakpoint)
@content
@mixin media--smartphone ()
@include media($breakpoint--s)
@content
@mixin media--tablet ()
@include media($breakpoint--m)
@content
I can make a button green, but red on smartphone and yellow on tablet.
.button
color: green
@include media--smartphone()
color: red
@include media--tablet()
color: yellow
When compiled, it would generate the following CSS with the media queries and the breakpoints:
.button {
color: green;
}
@media (width < 600px) {
.button {
color: red;
}
}
@media (width < 1000px) {
.button {
color: yellow;
}
}
Or its nested version:
.button {
color: green;
@media (width < 600px) {
color: red;
}
@media (width < 1000px) {
color: yellow;
}
}
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Desafíos de programación atemporales y multiparadigmáticos
Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.
Buy the bookWill you buy me a coffee?
This is how I keep writing without ads or paywalls.
Sure, it's on me!
Comments
There are no comments yet.