1 | # Media Queries, with Style |
---|
2 | |
---|
3 | `mq()` is a [Sass](http://sass-lang.com/ "Sass - Syntactically Awesome |
---|
4 | Stylesheets") mixin that helps manipulating media queries in an elegant |
---|
5 | way. |
---|
6 | |
---|
7 | As developers and designers we think in pixels and device families, so the |
---|
8 | `mq()` mixin accepts pixels, ems, keywords… and compiles into ems. |
---|
9 | |
---|
10 | We use `mq()` at [the Guardian](http://www.theguardian.com/uk?view=mobile) |
---|
11 | to effortlessly support older browsers and elegantly abstract media queries, |
---|
12 | as illustrated in this article posted on the Guardian's developer blog: |
---|
13 | [Mobile-first Responsive Web Design and IE8](http://www.theguardian.com/info/developer-blog/2013/oct/14/mobile-first-responsive-ie8). |
---|
14 | |
---|
15 | ## How to Use It |
---|
16 | |
---|
17 | 1. Install with [Bower](http://bower.io/ "BOWER: A package manager for the web"): |
---|
18 | `bower install sass-mq --save-dev` |
---|
19 | OR [Download _mq.scss](https://raw.github.com/guardian/sass-mq/master/_mq.scss) |
---|
20 | to your Sass project. |
---|
21 | 2. Import the partial in your Sass files and override default settings |
---|
22 | with your own preferences before the file is imported: |
---|
23 | ```scss |
---|
24 | // To enable support for browsers that do not support @media queries, |
---|
25 | // (IE <= 8, Firefox <= 3, Opera <= 9) set $mq-responsive to false |
---|
26 | // Create a separate stylesheet served exclusively to these browsers, |
---|
27 | // meaning @media queries will be rasterized, relying on the cascade itself |
---|
28 | $mq-responsive: true; |
---|
29 | |
---|
30 | // Name your breakpoints in a way that creates a ubiquitous language |
---|
31 | // across team members. It will improve communication between |
---|
32 | // stakeholders, designers, developers, and testers. |
---|
33 | $mq-breakpoints: ( |
---|
34 | (mobile 300px) |
---|
35 | (tablet 600px) |
---|
36 | (desktop 900px) |
---|
37 | (wide 1260px) |
---|
38 | |
---|
39 | // Tweakpoints |
---|
40 | (desktopAd 810px) |
---|
41 | (mobileLandscape 480px) |
---|
42 | ); |
---|
43 | |
---|
44 | // Define the breakpoint from the $mq-breakpoints list that should |
---|
45 | // be used as the target width when outputting a static stylesheet |
---|
46 | // (i.e. when $mq-responsive is set to 'false'). |
---|
47 | $mq-static-breakpoint: desktop; |
---|
48 | |
---|
49 | @import 'path/to/mq'; |
---|
50 | ``` |
---|
51 | 3. Play around with `mq()` (see below) |
---|
52 | |
---|
53 | ### Responsive mode ON (default) |
---|
54 | |
---|
55 | `mq()` takes up to three optional parameters: |
---|
56 | |
---|
57 | - `$from`: _inclusive_ `min-width` boundary |
---|
58 | - `$to`: _exclusive_ `max-width` boundary |
---|
59 | - `$and`: additional custom directives |
---|
60 | |
---|
61 | Note that `$to` as a keyword is a hard limit. It's not applying styles to the |
---|
62 | device (see examples below). |
---|
63 | |
---|
64 | ```scss |
---|
65 | .responsive { |
---|
66 | // Apply styling to mobile and upwards |
---|
67 | @include mq($from: mobile) { |
---|
68 | color: red; |
---|
69 | } |
---|
70 | // Apply styling up to devices smaller than tablets (exclude tablets) |
---|
71 | @include mq($to: tablet) { |
---|
72 | color: blue; |
---|
73 | } |
---|
74 | // Same thing, in landscape orientation |
---|
75 | @include mq($to: tablet, $and: '(orientation: landscape)') { |
---|
76 | color: hotpink; |
---|
77 | } |
---|
78 | // Apply styling to tablets up to desktop (exclude desktop) |
---|
79 | @include mq(tablet, desktop) { |
---|
80 | color: green; |
---|
81 | } |
---|
82 | } |
---|
83 | ``` |
---|
84 | |
---|
85 | ### Responsive mode OFF |
---|
86 | |
---|
87 | To enable support for browsers that do not support `@media` queries, |
---|
88 | (IE <= 8, Firefox <= 3, Opera <= 9) set `$mq-responsive: false`. |
---|
89 | |
---|
90 | Tip: create a separate stylesheet served exclusively to these browsers, |
---|
91 | for example with conditional comments. |
---|
92 | |
---|
93 | When `@media` queries are rasterized, browsers rely on the cascade |
---|
94 | itself. Learn more about this technique on [Jake’s blog](http://jakearchibald.github.io/sass-ie/ "IE-friendly mobile-first CSS with Sass 3.2"). |
---|
95 | |
---|
96 | To avoid rasterizing styles intended for displays larger than what those |
---|
97 | older browsers typically run on, set `$mq-static-breakpoint` to match |
---|
98 | a breakpoint from the `$mq-breakpoints` list. The default is |
---|
99 | `desktop`. |
---|
100 | |
---|
101 | The static output will only include `@media` queries that start at or |
---|
102 | span this breakpoint and which have no custom `$and` directives: |
---|
103 | |
---|
104 | ```scss |
---|
105 | $mq-responsive: false; |
---|
106 | $mq-static-breakpoint: desktop; |
---|
107 | |
---|
108 | .static { |
---|
109 | // Queries that span or start at desktop are compiled: |
---|
110 | @include mq($from: mobile) { |
---|
111 | color: lawngreen; |
---|
112 | } |
---|
113 | @include mq(tablet, wide) { |
---|
114 | color: seagreen; |
---|
115 | } |
---|
116 | @include mq($from: desktop) { |
---|
117 | color: forestgreen; |
---|
118 | } |
---|
119 | |
---|
120 | // But these queries won’t be compiled: |
---|
121 | @include mq($to: tablet) { |
---|
122 | color: indianred; |
---|
123 | } |
---|
124 | @include mq($to: tablet, $and: '(orientation: landscape)') { |
---|
125 | color: crimson; |
---|
126 | } |
---|
127 | @include mq(mobile, desktop) { |
---|
128 | color: firebrick; |
---|
129 | } |
---|
130 | } |
---|
131 | ``` |
---|
132 | |
---|
133 | ### Adding custom breakpoints |
---|
134 | |
---|
135 | ```scss |
---|
136 | $mq-breakpoints: mq-add-breakpoint(tvscreen, 1920px); |
---|
137 | |
---|
138 | .hide-on-tv { |
---|
139 | @include mq(tvscreen) { |
---|
140 | display: none; |
---|
141 | } |
---|
142 | } |
---|
143 | ``` |
---|
144 | |
---|
145 | ## Test |
---|
146 | |
---|
147 | 1. cd into the `test` folder |
---|
148 | 2. run `sass test.scss test.css --force` |
---|
149 | 3. there should be a couple of warnings like this one, this is normal: |
---|
150 | |
---|
151 | WARNING: Assuming 640 to be in pixels, attempting to convert it into pixels for you |
---|
152 | on line 25 of ../_mq.scss |
---|
153 | |
---|
154 | 4. if `test.css` hasn’t changed (run a `git diff` on it), tests pass |
---|
155 | |
---|
156 | ## Inspired By… |
---|
157 | |
---|
158 | - https://github.com/alphagov/govuk_frontend_toolkit/blob/master/stylesheets/_conditionals.scss |
---|
159 | - https://github.com/bits-sass/helpers-responsive/blob/master/_responsive.scss |
---|
160 | - https://gist.github.com/magsout/5978325 |
---|
161 | |
---|
162 | ## On Mobile-first CSS With Legacy Browser Support |
---|
163 | |
---|
164 | - http://jakearchibald.github.io/sass-ie/ |
---|
165 | - http://nicolasgallagher.com/mobile-first-css-sass-and-ie/ |
---|
166 | - http://cognition.happycog.com/article/fall-back-to-the-cascade |
---|
167 | - http://www.theguardian.com/info/developer-blog/2013/oct/14/mobile-first-responsive-ie8 |
---|