styles https://publish.mediacurrent.com/ en Using Sass Breakpoints Effectively https://publish.mediacurrent.com/blog/using-sass-breakpoints-effectively <span class="field field--name-title field--type-string field--label-hidden">Using Sass Breakpoints Effectively</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>There have been plenty of blog posts touting the reasons to use <a href="http://sass-lang.com/">Sass</a> as a CSS preprocessor, and if you've been doing responsive design for a while, you're probably already using the <a href="https://github.com/Team-Sass/breakpoint/wiki">Breakpoint</a> gem with Sass. But there are many ways to use both of these tools, so let's talk about using breakpoints effectively. </p> <blockquote><p>Start with the small screen first, then expand until it looks like sh*t. Time for a breakpoint!<br /> <em>- Stephen Hay.</em></p> </blockquote> <p>I must preface by saying that using device-based media queries *only* is not necessarily the best approach. It often makes more sense to inject breakpoints when you need them for a particular component. Some examples of when to add a breakpoint include:</p> <ul> <li>Based on your font size &amp; the size of the parent container, the line length may extend beyond the recommended number of characters for optimum readability (50-60 characters). Time for a breakpoint!</li> <li>Based on size of images within that container and text wrapping around those images, your layout no longer "works" visually, or information becomes disjointed or confusing to understand. Time for a breakpoint!</li> <li>It looks funky. Time for a breakdance! I mean breakpoint!</li> </ul> <p style="text-align: center;"><right><img alt="funky dancing" class="media-element file-original-media" data-entity-type="" data-entity-uuid="" height="371" src="https://publish.mediacurrent.com/sites/default/files/biglebowskidance.gif" style="width: 384px; height: 371px; margin: 0px auto;" typeof="foaf:Image" width="384" /></right></p> <p>That being said, it is still common that during the design process, teams will break down the design into stages for smartphones, tablets, and desktop. So if you are being asked to implement designs  like these, it is likely that you'll end up defining device-based breakpoints, even if you may deviate from them occasionally for reasons listed above.</p> <p>For me that meant that I would begin with variables like the ones below, which is a good start. </p> <pre class="line-numbers"> <code class="language-css">$phone-p: 319px $phone-l: 479px $tab-p: 639px $tab-l: 769px $desk: 1020px</code></pre><p>(Since we're talking about Sass and breakpoints, you can follow along and <a href="http://sassmeister.com/gist/3876bce41b061df2369e">see a demo on Sassmeister.com.</a>)</p> <h2>Min and Max Queries</h2> <p>Now for a while, I was using these variables for both min-width and max-width queries, which wasn't noticeable at first since the majority of queries tend to be min-width, because I use a mobile-first approach, meaning I begin at the mobile size and add on styles as the viewport gets larger. But there are times and places where it is more <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> to use a max-width query, especially if you are styling a component that only appears on mobile, like a mobile menu. Here's where I noticed the problem.</p> <p>If you use the same values for both min-width and max-width queries, you'll end up with overlapping styles at the 1px where those queries overlap. You'd either see whichever styles were more specific or printed last in the CSS, or more likely a combination of both.  To avoid this, if one media query stops at 770px, the next <em><strong>should</strong></em> start at 771px. For those of you playing along at home, if you have the <a href="http://sassmeister.com/gist/3876bce41b061df2369e">Sassmeister example</a> open and you squish the window to tablet size, you'll see that the box is either blue or has a pink border, but never both—which is what we want! Think of the pink box as the "mobile" menu and the blue box as the "desktop" menu.  </p> <p>So my first set of breakpoints are just for use with max-width, the second set are for use with the default regular breakpoint mixin, or max-width queries. </p> <pre class="line-numbers"> <code class="language-css">// For use with max-width only: // example: +breakpoint(max-width: $tab-l) $phone-p: 319px $phone-l: 479px $tab-p: 639px $tab-l: 769px $desk: 1020px $desk-full: 1079px // For use with min-width (default breakpoint mixin) // example: +breakpoint($desktop) $smartphone-portrait: 'screen' ($phone-p + 1px) $smartphone-landscape: 'screen' ($phone-l + 1px) $tablet-portrait: 'screen' ($tab-p + 1px) $tablet-landscape: 'screen' ($tab-l + 1px) $desktop: ($desk + 1px), 'no-query' '.lt-ie9' </code></pre><p>This might seem like a a fringe case scenario, but it's a problem we can easily avoid.</p> <h2>No-Query Fallbacks</h2> <p>Another advantage of this system: notice that the $desktop variable has the no-query fallback built in, which makes compiling a separate stylesheet for IE8 much easier; more on that in a minute. But If i were to try to use that the $desktop variable with max-width:</p> <pre class="line-numbers"> <code class="language-css">// don't do this: $desktop: ($desk + 1px) ,'no-query'; '.lt-ie9' +breakpoint(max-width $desktop) </code></pre><p>it would throw an error! So its preferable to have two sets of variables, one for min-width and one for max-width. </p> <p>And finally, I'd definitely encourage you to look into using a <a href="https://github.com/Team-Sass/breakpoint/wiki/No-Query-Fallbacks#separate-fallback-file">separate fallback file</a> to support older browsers. What this means is you end up with one ordinary CSS file with all your media queries, as you intended, and then you have a second CSS file with *no* media queries, but instead contains a prefix class like .lt-ie9 (less-than Internet Explorer version 9) for all queries meant for desktop browsers.</p> <p><img alt="One stylesheet with media queries, and one without." class="media-element file-original-media" data-entity-type="" data-entity-uuid="" height="626" src="https://publish.mediacurrent.com/sites/default/files/team-styles_css.png" typeof="foaf:Image" width="831" /></p> <p>To implement this solution, set up your Sass files like <a href="https://www.evernote.com/shard/s14/sh/5afc6366-76cf-4641-b23c-cf9c38753ef1/e374e24f2b1fbc250d3b35b7fb235910/res/d5879bba-b10c-4d99-8f33-9da5e3f7129a/skitch.png?resizeSmall&amp;width=832">this</a>:</p> <p><strong>styles.sass</strong></p> <pre class="line-numbers"> <code class="language-css">// Import Base theme base variables, mixins and extends: @import "base_utilities" // Then import base styles @import "base_components"</code></pre><p> <strong>no-query-styles.sass</strong></p> <pre class="line-numbers"> <code class="language-css">$breakpoint-no-queries: true $breakpoint-no-query-fallbacks:'.lt-ie9' !global // Re-import everything from styles.sass but without media queries. @import "styles"</code></pre><p>Then enable the <a href="https://drupal.org/project/conditional_styles">Conditional Styles module</a> and add this to your theme.info file:</p> <p><strong>theme.info</strong></p> <pre class="line-numbers"> <code class="language-css">stylesheets[all][] = css/team-elements.css stylesheets-conditional[lt IE 9][all][] = css/team-no-query.css stylesheets-conditional[(gte IE 9)|(gt IEMobile 7)|(!IE)][all][] = css/team-styles.css</code></pre><p>You can read all about the <a href="https://github.com/Team-Sass/breakpoint/wiki/No-Query-Fallbacks">no-query fallback methods on github</a>, but for what it's worth, setting up the desktop variable with the no-query fallback body class on it will ONLY print both the media query and the fallback if this flag is set:</p> <pre class="line-numbers"> <code class="language-css">$breakpoint-no-query-fallbacks: '.lt-ie9' !global</code></pre><p>Your CSS will include the lt-ie9 styles only (no media queries) if this flag is set:</p> <pre class="line-numbers"> <code class="language-css">$breakpoint-no-queries: true</code></pre><p><strong>The following section is not for the faint of heart</strong></p> <p><img alt="" class="media-element file-original-media" data-entity-type="" data-entity-uuid="" height="489" src="https://publish.mediacurrent.com/sites/default/files/shocked-baby.jpg" style="width: 257px; height: 209px; margin: 0px 0px 20px 20px;" typeof="foaf:Image" width="600" /></p> <p>You may have seen Chris Eppstein's blog post a few days ago titled, "<a href="http://chriseppstein.github.io/blog/2014/06/23/balancing-complexity/">Balancing Complexity in Sass</a>", which was very on-point in many ways. Sometimes we create such abstract code that it may add more confusion than it prevents. This just might be an example of that, but I thought I'd share in the hopes that perhaps someone has a cleaner way of implementing something like this!</p> <p>To save time, I wrote up some shorthand variables for all the combinations of the min and max breakpoints, which you can also view on <a href="http://sassmeister.com/gist/c684ee1e6f284dc28ece">Sassmeister</a>. Maybe it's unecessary? Maybe there's a better way? Maybe I'm variables crazy? Perhaps! Anyway, here's my whole breakpoint partial for your enjoyment.</p> <pre class="line-numbers"> <code class="language-css">// BREAKPOINTS $breakpoint-to-ems: true $print-media: 'print' $hidpi: min-resolution 143dppx // For use with max-width only: // +breakpoint(max-width: $tab-l) $phone-p: 319px $phone-l: 479px $tab-p: 639px $tab-l: 769px $desk: 1020px $desk-full: 1079px // For use with min-width (default breakpoint mixin) // +breakpoint($desktop) $smartphone-portrait: 'screen' ($phone-p + 1px) $smartphone-landscape: 'screen' ($phone-l + 1px) $tablet-portrait: 'screen' ($tab-p + 1px) $tablet-landscape: 'screen' ($tab-l + 1px) $desktop: ($desk + 1px), 'no-query' '.lt-ie9' // use // $breakpoint-no-queries: true // $breakpoint-no-query-fallbacks: '.lt-ie9' !global // at the top of a panel layout sass file to // re-render everything with .lt-ie9 for desktop media queries. ////////////////////////////// // COMBINATIONS // Phones $max-phone-p: 'screen' (max-width $phone-p) $max-phone-l: 'screen' (max-width $phone-l) $phone-p-phone-l: 'screen' ($phone-p + 1px) $phone-l // Tablets $max-tab-p: 'screen' (max-width $tab-p) $max-tab-l: 'screen' (max-width $tab-l) $phone-l-tab-p: 'screen' ($phone-l + 1px) $tab-p $phone-l-tab-l: 'screen' ($phone-l + 1px) $tab-l $tab-p-tab-l: 'screen' ($tab-p + 1px) $tab-l $tab-p-desk: 'screen' ($tab-p + 1px) $desk $tab-l-desk: 'screen' ($tab-l + 1px) $desk // All Mobile $mobile-device: 'screen' max-width $desk // High Resolution Devices $mobile-hi-res: 'screen' (max-width $desk) ($hidpi) $desk-hi-res: 'screen' (min-width $desk) ($hidpi) //Bonus: Mixin for &gt;IE9 *only* with no media queries @mixin fallback   @if $breakpoint-no-queries == true .lt-ie9 &amp; @content</code></pre><p>Hopefully this has been helpful, and I'm most definitely welcoming thoughts, comments and suggestions!</p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/about/our-team/mediacurrent-team" lang="" about="/about/our-team/mediacurrent-team" typeof="schema:Person" property="schema:name" datatype="" class="username">Mediacurrent Team</a></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 07/07/2014 - 16:02</span> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tags</div> <div class="field__items"> <div class="field__item"><a href="/tags/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tags/sass" hreflang="en">Sass</a></div> <div class="field__item"><a href="/tags/breakpoint" hreflang="en">breakpoint</a></div> <div class="field__item"><a href="/tags/media-queries" hreflang="en">media queries</a></div> <div class="field__item"><a href="/tags/css" hreflang="en">CSS</a></div> <div class="field__item"><a href="/tags/responsive" hreflang="en">responsive</a></div> <div class="field__item"><a href="/tags/rwd" hreflang="en">RWD</a></div> <div class="field__item"><a href="/tags/mobile" hreflang="en">Mobile</a></div> <div class="field__item"><a href="/tags/design" hreflang="en">Design</a></div> <div class="field__item"><a href="/tags/theming" hreflang="en">Theming</a></div> <div class="field__item"><a href="/tags/stylesheets" hreflang="en">stylesheets</a></div> <div class="field__item"><a href="/tags/styles" hreflang="en">styles</a></div> </div> </div> <div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="https://preview-misriptide.gtsb.io/blog/using-sass-breakpoints-effectively"></iframe></div> Mon, 07 Jul 2014 20:02:37 +0000 Mediacurrent Team 1757 at https://publish.mediacurrent.com