Understanding media queries

Media queries have been around since HTML4 and CSS2. Originally, the CSS media attribute was used to specify a different stylesheet to be loaded based on the media type loading the page, such as screen, TV, projection, or handheld. In HTML5, media queries also allow for expressions that check for other properties of the user agent viewing the document such as viewport width, height, resolution, and so on.

A media query is made up of two parts, namely a media type declaration and one or more expressions that evaluate to either true or false. Any CSS rules contained nested within the media query declaration are applied whenever any of the media query expressions evaluate to true. Alternatively, every CSS rule inside a stylesheet referenced by a link tag whose media attribute contains a truthy media query expression is applied to the specified media type.

// ---------------------------------
// Media queries on the HTML file
// ---------------------------------
<link rel="stylesheet"
  media="screen and (min-device-width: 960px)"
  href="default-style.css" />

// ---------------------------------
// Media queries within a CSS file
// ---------------------------------
@media screen and (min-device-width: 960px) {
  html, body {
    margin: 0;
    padding: 0;
  }

  /* ... */
}

Note

According to the specification, a browser is expected to, but not required to, continue to evaluate the expressions in media queries and update the CSS rules as changes take place in the browser environment. In other words, if two media queries are specified in a page—one for a window with a width below a certain size and one with a width above that value—the browser is not required to load the corresponding style sheet if the user manually resizes the browser width without refreshing the page. However, since this isn't a very common use case, it should not be of much concern to web designers. Besides, most modern browsers do in fact re-evaluate media query expressions in real time.

There are nine media types that can be specified and targeted from a media query. Alternatively, the keyword all can be used to indicate all media types. The allowed media types in CSS media types are as follows:

  • braille: Used for braille tactile feedback devices
  • handheld: Used for handheld devices
  • print: Used for printers
  • projection: Used for projectors
  • screen: Used for computer screens
  • tty: Used for media using a fixed-pitch character grid
  • tv: Used for televisions
  • embossed: Used for paged braille printers
  • speech: Used for speech synthesizers

The two operators that can be used to connect two or more expressions are the logical AND and OR operators, indicated by the and keyword and a comma character respectively. Additionally, the logical NOT operator can be used to negate an expression. This operator is indicated by the not keyword.

// Applies media queries to:
// viewport width between [200px, 450px] OR wider than orequals to 1200px
@media
  all and (min-width: 200px) and (max-width: 450px),
  (min-width: 1200px) {
  /* ... */
}

// Applies media queries to:
// non-printer viewport width between [200px, 450px]
// OR any media type wider than or equal to 1200px
@media
  not print and (min-width: 200px) and (max-width: 450px),
  all (min-width: 1200px) {
  /* ... */
}

The 13 values that can be checked inside media query expressions are width, height, device-width, device-height, orientation, aspect-ratio, device-aspect-ratio, color, color-index, monochrome, resolution, scan, and grid. So long as the expression makes sense, any combination of these values can be used in an expression. This is when some basic Boolean logic comes in handy as well as a bit of common sense.

Finally, the units that can be used along with each expression are the same as CSS units. We can use fixed units (such as pixels, centimeters, or inches) or relative units (such as percentages or ems). As a refresher, the following list describes the possible units used in CSS, and thus, in media query expressions:

  • %: percentage
  • in: inch
  • cm: centimeter
  • mm: millimeter
  • em: em (1 em = height of current font size)
  • ex: ex (1 ex = height of a font)
  • pt: point (1 point = 1/72 inch)
  • pc: pica (1 pica = 12 points)
  • px: CSS pixels

The rest of this section will contain a more detailed explanation of each of the valid values used in media queries, along with examples for each.

width

When queried against a continuous media type, the value refers to the total viewport (visible window area) width of the device, including any rendered scroll bars. When queried against a paged media type, the total width measured against is the width of the output page.

Optionally, the prefixes min and max can be used with the width keyword, allowing us to specify ranges, rather than discrete values.

@media all and (min-width: 250px) {
  body {
    background: red;
  }
}

@media all and (max-width: 249px) {
  body {
    background: blue;
  }
}

The preceding snipped specifies two media queries that apply to all media types. When the output width is less than 250 (exclusive), the background color is set to blue. Otherwise, the background color becomes red. As is the case with most modern browsers, we can resize the browser window manually and the new CSS rules will apply automatically. Otherwise, the properties are tested and set at the time the browser renders the page the first time.

In the following illustration, the window on the left is not quite wide enough to trigger the first media query on the previous snippet, which causes the second snippet to evaluate to true. By simply resizing the browser window (which can be done by maximizing the browser or possibly by simply turning the mobile device into landscape mode), the second media query will be invalidated and the first one will become enabled.

width

Note that the units used in the previous media query evaluation are CSS pixels. When setting special rules for media types where pixels don't apply very easily, we can use other units such as in (inches) or cm (centimeters), as seen in the following example:

@media print and (min-width: 7.0in) {
  h1 {
    color: red;
  }
}

@media print and (max-width: 6.5in) {
  h1 {
    color: blue;
  }
}

The output of the previous code snippet can be seen in the following screenshot. Note that the minimum and maximum width in question is not necessarily the width of the page in which the printing takes place, but rather the width of the box formed by the paper width minus any margins set by the printer. In this case, a sheet of paper of 8.5 inches in width, minus a single inch from the left and right margins, makes an effective width of 6.5 inches in portrait mode. The landscape version of that same page, which is 11 inches wide, produces a box width of 9 inches, which is wide enough to trigger the first media query.

The top print preview on the following screenshot represents a page being printed in portrait mode. That is, its width (in this case) is no more than 6.5 inches. The preview on the bottom is wider than 7.0 inches which causes a different media query to enable, thus changing the stylesheet settings for the page to be printed.

width

height

Similar to the width property, the height property refers to the viewport height of a continuous media type, including rendered scroll bars. For paged media types, this refers to the effective page box available to the output media. Needless to say, the value of a height property cannot be a negative unit. Again, just like the width property described previously, we can also add the modifier prefixes min and max to this property in order to specify ranges of values, rather than unit-perfect single values.

@media all and (min-height: 500px) {
  article {
    width: 100%;
    float: none;
  }
}

@media all and (max-height: 499px) {
  article {
    width: 33%;
    float: left;
  }
}

device-width

Similar to the width property, the device-width refers to the entire physical window or page, regardless of the current browser window's width or available output width of a paged media.

@media all and (min-device-width: 1601px) {
  h1 {
    color: red;
  }
}

@media all and (max-device-width: 1599px) {
  h1 {
    color: green;
  }
}

@media all and (device-width: 1600px) {
  h1 {
    color: blue;
  }
}

In the previous code example, if the screen width (not browser width) is exactly 1600px, the last media query will be active, regardless of any browser resizing. The same goes for a page—if the entire width of the page calculates to exactly 1600px wide, the corresponding media query will match. Anything more or less than that and one of the other two media queries will be used instead. Again, the keywords min and max are valid modifiers that we can use in conjunction with this property.

The answer to the question about when to choose device-width or width and vice-versa is simple: whenever the design of your application calls for it. In most cases, the end result is the same. The only time when width is more appropriate than device-width is when the user might use their browser windowing in a customized size (not maximized) and the design is intended to reflow and auto adjust to the current width of the browser. On the other hand, if a design is meant to remain the same on a certain monitor width (or range of widths) regardless of the current browser state, then device width might be a more elegant and efficient way to go about it.

device-height

Finally, the last possibility with querying the rectangular sides of a display, device-height works exactly the same as device-width (other than the size measured). Although the same result can be achieved with the other viewport queries described so far, out of the four queries described so far, device-height might be the ideal candidate (along with device-width) to identify mobile orientation (portrait or landscape).

orientation

Since media queries don't allow for comparison between two attributes (for example, if width is greater than or equal to height), orientation allows us to determine which way a media type is rotated. Had there been comparison operators included in the CSS media query engine, we could easily determine if a page was in landscape mode. To do that, we simply need to determine if the width is greater than the height. If the two sides are of the same length (a square viewport), the specification determines the media to be in portrait mode. However, since such an approach is not possible directly with media queries, we can instead use the much more intuitive orientation attribute.

The two possible values for the attribute are, with little surprise, portrait and landscape. The prefixes min and max are not allowed with this query, since it doesn't make sense to classify something as being at least landscape or no more than portrait.

@media all and (orientation: portrait) {
  body {
    backgroundcolor: red;
  }
}

@media all and (orientation: landscape) {
  body {
    backgroundcolor: green;
  }
}

@media all and
  not (orientation: portrait) and
  not (orientation: portrait) {
  body {
    backgroundcolor: blue;
  }
}

In the previous example, we check if the media is either landscape or portrait. Whatever the orientation evaluates, the media query becomes activated. Note that the third query attempts to set a third orientation based on erroneous conclusions. One might imagine that the way to determine if something is landscape or portrait is to take the ratio between the two—if the width is greater than the height then the media is in landscape mode, otherwise it is in portrait mode. You can imagine how someone might conclude that if both sides (width and height) are the same, that the orientation is neither landscape nor portrait. However, it is important to remember that a square figure is not landscape, but is indeed portrait. The key is to remember that there are only two possible values for this property, precisely because there are only two possible states that a media can be in at a time.

aspect-ratio

The aspect ratio property allows us to check for the proportion of the media's width relative to its height (in this order). This property takes into account the actual ratio between the width and height media query values, meaning that dynamic changes to the viewport width and height affect this property directly. The min and max keywords can be used in the evaluation of this property.

// Aspect ratio is exactly twice as high as wide
@media all and (aspect-ratio: 1/2) {
  h1 {
    color: blue;
    font-size: 1.0em;
  }
}

// Aspect ratio is at least three times as high as wide
@media all and (min-aspect-ratio: 1/3) {
  h1 {
    color: red;
    font-size: 0.5em;
  }
}

// Aspect ratio is no more than four times as wide as high
@media all and (max-aspect-ratio: 4/1) {
  h1 {
    color: green;
    font-size: 3.0em;
  }
}

// Aspect ratio is an exact square
@media all and (aspect-ratio: 1/1) {
  h1 {
    color: yellow;
    font-size: 2.0em;
  }
}

// Aspect ratio is no more than half as high as wide – ERROR!
@media all and (max-aspect-ratio: 1/0.5) {
  h1 {
    color: green;
    font-size: 3.0em;
  }
}

The previous code snippet demonstrates various ways to calculate aspect ratio. Keep in mind that the value of this attribute must always read as a single fraction, with no floating point numbers involved. Simply said, the value must be in the form of an integer, followed by a slash, followed by a second integer. The first integer refers to the width value and the second to the height. Together, they form a ratio.

The first media query in the previous example tests for a viewport that is exactly two width units for every one width unit. Put it another way, that expression checks for a viewport that is twice as high as it is tall or half as wide as it is wide. In contrast, the last media query attempts to generate the same result, but in reverse. The attempt there was to query a media type that was at most twice as wide as it is tall. This expression would raise a silent expression (the expression would be ignored), because the format is not appropriate. Instead of checking for 1/0.5, the proper way would be to make it 2/1, making the width length twice as large as the height.

When specifying a desired value for a media query aspect-ratio expression, the number on the left refers to the width relative to the height, which is represented by the value on the right. Both numbers must be positive integers and the larger of the two values can be on either side. Alternatively, both values can be the same, which would test for a square aspect ratio (1/1).

aspect-ratio

device-aspect-ratio

Checking for device-aspect-ratio works the exact same way as the aspect-ratio, as explained previously, with the only difference being that the width and height references are based on the device-width and device-height, as explained in their respective sections.

Again, as with device-width and device-height, this is a great way to check for the underlying fingerprinting of the device accessing the application, which is independent of the current state of the browser window at the time the media query is tested. As far as responding to user actions, testing for aspect-ratio might be a better solution than device-aspect-ratio as the user might change the dimensions of the browser window independently of the device-screen-ratio. However, in order to determine the device's true aspect ratio, the alternative would be to use device-aspect-ratio.

Also, keep in mind that it is quite possible to define redundant media queries when querying the aspect ratio. In a case such as this, as is the case with CSS, the last matching expression overrules previous duplicated expressions and values.

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 1/1) {
  h1 {
    color: blue;
    font-size: 3.0em;
  }
}

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 1/1) {
  h1 {
    color: red;
    font-size: 3.0em;
  }
}

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 2/2) {
  h1 {
    color: green;
    font-size: 0.5em;
  }
}

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 10/10) {
  h1 {
    color: purple;
    font-size: 0.5em;
  }
}

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 2000/2000) {
  h1 {
    color: orange;
    font-size: 10.5em;
  }
}

// Aspect ratio evaluates to 1/1
@media all and (device-aspect-ratio: 17/17) {
  h1 {
    color: transparent;
    font-size: 0.0em;
    display: none;
  }
}

The previous code example shows six media query expressions, all of which evaluate to the same aspect ratio. Whether the original expressed ratio is a duplicate of a previous value or a different value that reduces to the same ratio, the end result is the same. When equal ratios are found and no other expression breaks the tie by further qualifying the whole expression, then the last occurrence of the duplicate expression becomes the only active query for values not unique to the previous expressions. For example, if two or more expressions evaluate to the same aspect ratio, whatever CSS attributes that both expressions had in common are given priority to the last occurrence of the query. Unique values between each expression get cascaded to the final evaluation.

// Aspect ratio evaluates to 1/1
//  Properties set: color, font-size
//  Properties overridden: none
@media all and (device-aspect-ratio: 1/1) {
  h1 {
    color: blue;
    font-size: 1.5em;
  }
}

// Aspect ratio evaluates to 1/1
//  Properties set: color, border, padding
//  Properties overridden: color
@media all and (device-aspect-ratio: 1/1) {
  h1 {
    color: red;
    border: 1px solid green;
    padding: 20px;
  }
}

// Aspect ratio evaluates to 1/1 and anything landscape
//  Properties set: color
//  Properties overridden: color
@media all and (min-device-aspect-ratio: 1/1) {
  h1 {
    color: green;
  }
}

In the previous code snippet, three separate media queries evaluate to the same aspect ratio. The last query also uses a min modifier, meaning that it matches any aspect ratio that is not 1/1 (as well as any aspect ratio that is exactly 1/1), but the device width is still larger than the height (in other words, any media types of aspect ratio 1/1 and any media types of orientation landscape).

In this case, when a media type is landscape (remember a square or 1/1 aspect ratio is never considered landscape), only the third query matches the current state. Thus, only the color attribute is assigned to the h1 tag specified in that media query. However, when the aspect ratio is in fact 1/1, then all three of media queries evaluate to true, thus all three queries are applied to the elements they specify.

The first query only sets a color of the tag to green. The second query resets that tag color and additionally applies a few more attributes to the tag. Finally, the third query again resets the tag color, but doesn't touch any other property. The final result for these composite queries for a media type with a 1/1 aspect ratio can be seen in the following code snippet.

@media all and (device-aspect-ratio: 1/1) {
  h1 {
    color: green;
    border: 1px solid green;
    padding: 20;
  }
}

color

This media query attribute checks for the number of bits per color component used by the output device. For example, if the output device uses an 8-bit color system, where it uses 2 bits to represent the red, green, blue, and alpha components, then the color attribute in the media query expression is 2. The min and max modifiers can also be used to test for this as well.

@media all and (color: 2) {
  h1 {
    color: green;
    border: 1px solid green;
    padding: 20;
  }
}

If the output device is not a color device then the value of the color attribute will be zero.

@media all and (color: 0) {
  h1 {
    color: green;
    border: 1px solid green;
    padding: 20;
  }
}
// This query produces the exact same result as the previous one
@media all and (min-color: 1) {
  h1 {
    color: green;
    border: 1px solid green;
    padding: 20;
  }
}

In some instances, where the output device uses different bit counts per color component, the color attribute refers to the smallest value of bits per component. For example, if the output device uses an 8-bit color system and it uses 3 bits for the red component, 3 for the green component, and 2 for the blue component then the value used as the color attribute for the media query will be 2.

color-index

The color-index attribute returns the number of colors used by the output device. For example, a device with 256 colors would match the following media query exactly:

@media all and (color-index: 256) {
  h1 {
    color: green;
    border: 1px solid green;
    padding: 20;
  }
}

As with the color attribute, values specified for the color-index attribute cannot be negative. Also, if the output device does not use a color lookup table, the value for color-index is zero.

monochrome

If an output device is monochrome, this media query attribute refers to the number of bits per pixel used by device. This is similar to color, but only applies to monochrome devices and, for obvious reasons, only for a single pixel, as opposed to the lowest color component.

@media all and (monochrome: 1) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

If the device is not monochrome, this attribute will match a value of zero. Also, we can use the min and max modifier keyword to target ranges. Alternatively, a single Boolean expression can be used to determine whether the device is monochrome or not.

@media not all and (monochrome) {
  h1 {
    color: red;
    border: 1px solid purple;
    padding: 20;
  }
}

// This query produces the exact same result as the previous one
@media all and (color) {
  h1 {
    color: red;
    border: 1px solid purple;
    padding: 20;
  }
}

resolution

Contrary to what one might be led to believe, the resolution attribute does not query the screen resolution as in the resolution we can set to our monitor through the operating system. Instead, the resolution attribute queries the pixel density (or dot density in the case of a printer) measured in dpi (dots per inch or pixels per inch) as well as dpcm (dots or pixels per centimeter).

@media all and (resolution: 300dpi) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

The min and max modifiers are valid in this query expression. If the output device does not use square pixels, using min-resolution queries against the least dense dimension of the output device. When a max-resolution query is issued, the most dense dimension of the output device is used to evaluate the expression.

scan

When rendering on a television, the scan attribute queries the scanning of the device. The only possible values are progressive and interlace. Using the min and max modifiers does not make sense in the context of a television's scan process and thus makes an invalid expressions.

@media all and (scan: interlace) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

@media all and (scan: progressive) {
  h1 {
    color: red;
    border: 1px solid red;
    padding: 20;
  }
}

grid

A grid output device is one that is not a bitmap-based device. Querying the grid attribute returns true when the output device is not bitmap-based. The only possible values to query against are 1 and 0. The min and max modifiers are not valid in this query.

Examples of grid-based devices include any device that uses a character grid, such as those older calculators or even older model cell phones with fixed fonts.

// Evaluates to true on grid-based devices
@media all and (grid) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

// Evaluates to true on grid-based devices
@media all and (grid: 1) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

// Evaluates to true on bitmap-based devices
@media all and (grid: 0) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}

// Evaluates to true on bitmap-based devices
@media not all and (grid) {
  h1 {
    color: black;
    border: 1px solid black;
    padding: 20;
  }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.133.160