Media queries allow us to style elements dynamically based on conditions of the output device, aka the viewport. This includes size, resolution, etc. Most commonly used in responsive web design.
Good examples of media queries being used: mediaquer.is – showcases sites that use them well.
A media query is a style block containing one or more logical expressions that are either true or false. The @media rule specifies the media type we want to target. There are several you can use. If you do not specify one, the all type will be applied, which specifies to all devices. For browsers, you select the screen media type. Next, you put in the and keyword, which is called a logical operator, and combines the screen media type, with the media feature/expression that will go inside the parenthesis. The expression is what checks for the true/false conditions of the media features defined. Some of the features you can include are width and height. All usable are listed here.
We’ll set this one max-width: 768px. Note, for these you do NOT use a semicolon at the end. You then enter the css rules inside the curly brackets, which will be applied when the conditions are true. So, if the media type is a screen, and the browser viewport is 768px or less, these styles will be applied.
Remember: max-width is anything equal to or less than the width defined. min-width is anything equal to or greater then the width defined.
Now, we’ll add a second media query for a smaller screen size. Notice how the font is still white. That’s because the color property from the first one is still true (the screen is less than 768px), we only overwrote the background color.
Now let’s say you wanted these changes only at a certain range. You can combine expressions to get more specific. In the example below, by using and again we’ve combined the two media features, so the styles will only be applied if both are true. Now the text does not maintain the white color because the conditions are no longer true.
There are other ways to create media queries in a document. You can have them in a separate stylesheet, then link that to the html document like you would any other one with the link element. Be sure to list them below the main stylesheet, or they’ll be overwritten by it. You also use the media attribute to specify the conditions that must be true for the styles in that stylesheet to be applied. The downside to this method is we need to include multiple link tags, one for each media query, which mean multiple requests to the server, which mean it will slow things down. Another drawback is that these stylesheets still have to download, even if the media query returns false and its styles don’t apply to anything. What’s better about the first method is they’re only loaded when the conditions are true.
Finally, you can also add them via an import directive. These work the same way as the example above, and will import the files if the conditions are true. But, like mentioned before, @import can cost you performance, as each one is a different server request. The best way is still the first way we went over.
Lastly, let’s make it so that the text doesn’t get too wide when the browser is really wide. In the example below, when the browser size is at least 1000px, the new width is applied to the wrapper div.
Adaptive layouts with media queries
Logical operators allow you to create more complex media queries (like and seen early, which combines the screen media type with the media feature listed in the parenthesis). Other ones include not, which is used to negate an entire media query. It will return true if the media query would otherwise return false. In the example below, we’re telling the browser that if its not on a monochrome screen (like a black and white one), then make the background color red. Since we’re on a color display, the browser sees it as true (since it’s not a monochrome one).
If we were to change the media feature to color, the browser would see this as false, because it’s not not color. So, it would turn the background red only if the screen was not color.
Currently the page has a one column layout regardless of screen width, but in reality we’d probably only want that for smaller, mobile browsers. Because our base styles are already optimized for that, there’s not much we need to do. This is the mobile first approach that we saw with the first treehouse lesson on “How to make a website”. Now we just need to add media queries on top of that for our larger viewports.
If some of the parts of the page aren’t necessary for when you first view the mobile page, you can temporarily hide them, then reveal them as the screen gets larger. In the example below, since we’re doing a mobile first approach, we can set the base style for the Extra div to display: none;, then change it later with a media query.
Next, we’ll make it so the content becomes two columns after a certain width. With the media query below, we’re saying that when the viewport width is at least 481px, apply these styles. We’ve made the div’s (each with the class .col) float left, then set widths for them with super exact percentages so they’ll scale nicely with the page. We then added a margin-left for the second one as well to put some space between them (we could have also added an equivalent margin-right to the first div, the effect would have been the same).
Another logical operator is only, which is used to apply the styles only if the entire query matches. This is useful for preventing older browsers that do not support media queries from applying the given styles, otherwise they’d apply all styles in any media query immediately. The browsers that do support media queries will ignore the only and apply the styles like they normally would according to the conditions set.
So, finally we want to adjust the styling for desktops. First, we’ll add a media query that tells the browser only to apply it when the viewport is at least or greater than 769px. Then, for the styles we floated the .logo (for the logo) left and the nav links to the right, since the screen’s too wide for them to remain in the center. Then, we made the Extra div reappear by setting its display:block;, and gave it a width and a margin-left and readjusted the width of the .main div to have them all fit nicely in one row.
Now, notice that the margin-left code was repeated for the .extra and .secondary div from the previous media query. To make this cleaner, remove it from the second and put it in the first media query to combine them into one selector.
Finally, let’s once again add a media query to keep things at a fixed width once the viewport gets very wide. By setting the .wrap div to a set width, we ensure the content within it never gets too stretched out. It’s saying is the width is at least or greater than 1024px, then apply this style.
The previous media features were based on things like viewport width and height, but there are more device specific ones we can use that refer to the entire screen area. They don’t look for a specific device, but instead its capabilities, like min or max device width or pixel ratio or resolution.
Here, we start with a fluid, responsive site with a breakpoint for mobile devices. However, if you were to open the site on an iphone, it wouldn’t use the media query.
This is because smartphones use a virtual viewport that’s larger than the actual screensize, which lets it fit everything in to its screen. To fix this, there’s a special html meta tag that instructs the device on how to handle the viewport size on mobile devices. Set the name attribute to viewport and the content attribute to device-width. The width property sets the size of the viewport, and the value device-width is 100% of the viewport screen. You can see how this make the media query work now, since the viewport’s width is adjusted to what it actually is.
Now for some device-specific media features. The device-width one defines the whole width of the devices screen based on its orientation These can also be prefixed with min and max like before. In the example below, any device with a viewport equal to or less than 479px would have these styles applied and hide the comments section. Notice how it does not work on the web browser, as this is only affecting devices with a full screen of 479px or less. Even thought the web browser’s viewport width is less than 479px, it’s not actually checking for that. It’s actually checking for the entire screen width of the computer desktop.
The orientation media feature indicates whether the device is in landscape or portrait mode. Portrait means taller than it is wide, and landscape is wider than it is tall. In the example below, when the device is in portrait mode, the body’s background color will turn red, but not if it’s in landscape mode. If we set orientation: landscape, the opposite results would be true.
You need to be careful with orientation though because it will also affect desktop browsers. With the code below, if the browser is wider than it is tall, then is will be considered to be in landscape mode and the styles will be applied. If it’s taller than it is wide, it will be in portrait mode and the styles won’t be applied.
However, due to the variety of devices that are out and will come out, to future proof it’s best to avoid device-width and orientation, and use min-width and max-width instead.
Two of the most useful device media features are device-pixel-ratio and resolution. These let us detect the difference between the device pixels and the logical pixels, or the physical resolution vs the logical resolution.
The device-pixel-ratio is the difference between the device’s logical pixels and physical pixels. For example, the iphone has a ratio of 2, because the physical resolution on a retina display is double the logical resolution. It has twice as much pixel density. The physical resolution on the latest iPhone is 640 x 1136 pixels, while the logical resolution, or the actual size of the screen, is half of that, 320 x 568.
So, for example, when developing for a device with a pixel ratio of 1, one CSS pixel will be exactly one physical pixel on screen. But if the pixel ratio is 2, then one CSS pixel will be depicted on screen as two physical pixels. It doubles it.
When we switch to the retina view in the simulator, the window gets twice as big, because the desktop doesn’t have the resolution to support it. If we were using a retina display then it could support it.
You can also use min and max as a prefix for these as well . In the example below, when the device-pixel-ratio is at least 2 or bigger, the styles will be applied. You should use the -webkit- prefix to support older webkit based browsers that don’t support resolution yet.
The resolution media feature has much stronger device support, and describes the resolution of the device, aka the pixel density. The display resolution of a screen is the total amount of pixels available. ppi and dpi are describing the same thing.High resolution displays can really affect how elements appear, especially images, which can look blurry or grainy is not optimized for higher resolution screens. In the example below, the pic was only 45px wide, so in the retina display, everyone of its pixels is being doubled.
We can fix this with the media features mentioned above, by having it use a higher definition picture based on the resolution of the screen. In the example below, these two media queries are testing for the same feature. Remember, -webkit-min-device-pixel-ratio is only for those older, webkit based browsers that don’t support the resolution media feature. The comma between the two is just like using the word or. So, we’re telling the browser, if it’s a webkit based browsers with a device-pixel-ratio of 2 or high, or a device with a minimum resolution of 192dpi or greater, then apply this style.
So, 2 x 96 = 192dpi.
Now, it’s using the new, higher res image, but it looks too big.
This is good, because it shows the media query is working. Now we just need to adjust the background size.
A good catch all for high resolution devices is a min-device-pixel-ratio: 1.5 and a min-resolution of 144dpi. If you don’t want to do the math (1.5 x 96), you can use the new unit dppx which represents the number of dots per pixels. This maps perfectly to the ratio value of min-device-pixel-ratio, so you don’t need to do the multiplication for dpi. This does lack some browser support though, so use dpi for now.
Many users rely on being able to print pages from websites, so you can create a print stylesheet to format a webpage so that when printed it is in a good format for that.
Sites that do this well: http://www.smashingmagazine.com/. Notice how it removes the non-article related stuff for the print version.
We’ll start with the example site below. Right now the print format looks bad.
When making a print stylesheet, you need to look at the elements and think about what you can cut back, as you’re limited to a physical space of 8 1/2 by 11″. So, you may want to remove the comments and navigation sections. Also, since print is static, you must consider the interactive elements like links.
You use the print media type rather than the screen one, and tells the browser to apply the styles only when printing a page. We’ll start with some basic styles that are needed for print to prevent excessive printing, like setting the background to transparent (which turns off any background images), the font color to black and turning off shadows. !important makes it so this rule will be applied over any others, and the * is the universal selector which selects all elements on the page.
Next, we’ll remove some elements we don’t need, like the search, sidebar, main-nav, comments and footer sections. Already it’s looking way better.
Next, we’ll fix the margin for the header, remove the blue border at the top, and center align it.
Next, we’ll create print friendly links. We’ll use the attribute selector to select links that have the href attribute, then the ::after psuedo element to insert content after them. In this case, the content is the value of the href attribute.
Now, you normally don’t want every link displayed, you’ll want to avoid relative links, which are typically used for images and page anchors. To fix this, use the begins with substring matching attribute selector to only select links that begin with http.
You can define margins around the printed page using the @page rule. Physical units work well here. This also appears to have removed the date and page markings.
You can also determine page breaks, like if you wanted to prevent them after headings or unordered lists with the page-break-after property, by setting it to avoid. This will force it to break before them (in this case ul and h2) instead.
We can avoid orphans and widows by using the orphans and widows properties. Orphans are the single words or straight line that are left alone after a page break and widows are the ones that fall before a page break. By setting each to 3, the page won’t orphan or widow anything less than the 3 lines specified here.
You also should probably reduce the font size. We’ll use the previous rule (remember, DRY!) and add ul as a selector, then use a physical unit for the font-size.
Finally, you can remove images if you don’t need them. Once again, we’ll use the rule we already have and just add the img selector to it.
And holy moly, that’s it! Finally done the CSS Foundations Deep Dive! Woooooooo! Only took like 1 and a half months, but it was worth it to get such good notes out of it.