breakpoint 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 Sass Breakpoint Mixin Meets IE8 https://publish.mediacurrent.com/blog/sass-breakpoint-mixin-meets-ie8 <span class="field field--name-title field--type-string field--label-hidden">Sass Breakpoint Mixin Meets IE8</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>If you're familiar with Sass, you're probably well aware of the <a href="http://breakpoint-sass.com/">Breakpoint mixin</a> and it's awesomeness. It's a tool that makes using media queries extremely easy. Instead of having to break up your CSS into large chunks by breakpoint or even into separate stylesheets, you can organize your CSS by base elements, layout, module, state, or theme. Note that these terms are not Drupal terms, for more information on how to categorize your Sass, check out the <a href="http://smacss.com/book/categorizing">SMACSS e-book by Jonathan Snook</a> and also this handy <a href="https://github.com/tinganho/smacss-sass-template">SMACSS</a> template.</p> <p style="margin-bottom: 0px; padding-bottom: 0;">Enter breakpoint, which allows you to inject media queries wherever necessary. Say you are creating menu lists in the footer of your site. In a desktop view, you may want the menu blocks to sit side-by-side, but on mobile they should stack vertically. So your Sass breakpoint mixin may be something simple where you define a mobile first strategy with two breakpoints for tablet and desktop:</p> <pre class="line-numbers"> <code class="language-css">@import "breakpoint"; $tablet: 500px; $desktop: 960px;</code></pre><p>So in your code, you can utilize your breakpoint mixin like this:</p> <p style="margin-bottom: 0px; padding-bottom: 0;"><strong><em>.scss syntax OR</em></strong></p> <pre class="line-numbers"> <code class="language-css">#footer .menu-block { width: 96%; margin: 0 2%; @include breakpoint($desktop) { width: 29.5%; }</code></pre><p style="margin-bottom: 2px; padding-bottom: 0;"><strong><em>.sass syntax (shorthand)</em></strong></p> <pre class="line-numbers"> <code class="language-css">#footer .menu-block width: 96% margin: 0 2% +breakpoint($desktop) width: 29.5% </code></pre><p style="margin-bottom: 2px; padding-bottom: 0;"><strong>which will output css like this:</strong></p> <pre class="line-numbers"> <code class="language-css">#footer .menu-block {   width: 96%;   margin: 0 2%; } @media (min-width: 960px) { #footer .menu-block { width: 29.5%; } }</code></pre><p>Brilliant! But... a couple things you may not have considered is 1) the effect on performance and 2) how you can use breakpoint to retrofit Internet Explorer 8.</p> <h3>1. Performance Considerations</h3> <p>As you can imagine, this method makes media queries easy to use and helps keep your Sass organized. But what about the resulting CSS? This means you will end up with media queries sprinkled throughout your CSS. Won't this make everything load slower? As it turns out, the effects on performance are almost nil. Check out this great case study at <a href="http://sasscast.tumblr.com/post/38673939456/sass-and-media-queries">sasscast.tumblr.com</a> to see exactly how this plays out. In the case study, a <a href="http://aaronjensen.github.com/media_query_test/">test scenario</a> was created that included 2000 queries. In one result, all the queries were separate (which is how the breakpoint output looks) and the other where they are all combined. The resulting difference was a couple hundred milliseconds, which when you factor in caching becomes almost entirely negligible.</p> <h3>2. Backwards Compatibility for Older Browsers</h3> <p>Another problem that creeps up when using the breakpoint mixin and fragmented media queries is how to easily make a custom stylesheet for IE8 (or 7) so that these older browsers will be able to understand the queries. It is true that there are various javascript solutions like <a href="https://github.com/scottjehl/Respond">respond.js</a> or <a href="https://code.google.com/p/css3-mediaqueries-js/">css3-mediaqueries-js</a>, but if you are dealing with a large site or complex caching methods... then these may not be viable options. </p> <p style="margin-bottom: 2px; padding-bottom: 0;">Why not let Sass do the work for you? After you've got your basic breakpoint mixin created, then you can create a special mixin for desktop (or whichever breakpoint is appropriate that you want to use to apply those same styles to IE8).</p> <p style="margin-bottom: 0px; padding-bottom: 0;"> <strong><em>.scss syntax OR</em></strong></p> <pre class="line-numbers"> <code class="language-css">@mixin desktop {   @include breakpoint($desktop) {   @content   }   .old-ie &amp; {   @content   } } </code></pre><p style="margin-bottom: 0px; padding-bottom: 0;"><strong><em>.sass syntax (shorthand)</em></strong></p> <pre class="line-numbers"> <code class="language-css">@mixin desktop   +breakpoint($desktop)   @content   .old-ie &amp;   @content </code></pre><p>Then in your Sass stylesheet, use @include desktop instead of @include breakpoint(desktop). Sass will then create both the media query with the appropriate styles, and the same styles with the prefix of .old-ie (or whatever you want to name it). In reality, if you have lots of breakpoints you could create matching mixins for all breakpoints, which would make the amount of text you have to type even shorter!</p> <p style="margin-bottom: 2px; padding-bottom: 0;"><a href="http://note.io/14hkbfq"><img alt="Breakpoint Internet Explorer 8" data-entity-type="" data-entity-uuid="" height="587" src="/sites/default/files/example.scss_.png" style="max-width: 100%; height: auto; display: block;" title="Breakpoint Internet Explorer 8" width="872" /></a></p> <p><a href="http://sassmeister.com/gist/starryeyez024/6168597">See this code in action at sassmeister.com.</a></p> <p style="margin-bottom: 2px; padding-bottom: 0;">Finally, to bring it all together, simply add an IE conditional statement to your html so that older versions of Internet Explorer will pick up these styles. Here's an example:</p> <pre class="line-numbers"> <code class="language-css">&lt;!--[if lt IE 9]&gt; &lt;html class="old-ie"&gt; &lt;![endif]--&gt; </code></pre><p>Now you can continue to use object-oriented Sass while keeping IE8 users happy!</p> <p><img alt="" data-entity-type="" data-entity-uuid="" src="/sites/default/files/high-five.gif" /></p> <p>UPDATE:  You can take this a step farther and build in your fallbacks into your <a href="https://github.com/Team-Sass/breakpoint/wiki/No-Query-Fallbacks">Breakpoint variable</a> (thanks <a href="https://twitter.com/codingdesigner">@codingdesigner</a>!).</p> <p><strong>Additional Resources</strong></p> <p><a href="https://www.mediacurrent.com/blog/webinar-elegant-css-drupal%25E2%2580%2594less-vs-sass">Elegant CSS In Drupal—LESS vs Sass</a> | Webinar </p> <p><a href="http://www.mediacurrent.com/blog/controlling-your-site-layout-using-mobile-first-omega-theme">Controlling Your Site Layout Using The Mobile-First Omega Theme</a> | Webinar</p> <p><a href="http://www.mediacurrent.com/blog/tapping-drupal-7-responsive-adaptivetheme">Tapping into the Drupal 7 Responsive AdaptiveTheme</a> | Blog</p> <p> </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">Thu, 08/08/2013 - 10:56</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/breakpoint" hreflang="en">breakpoint</a></div> <div class="field__item"><a href="/tags/compatibility" hreflang="en">compatibility</a></div> <div class="field__item"><a href="/tags/css" hreflang="en">CSS</a></div> <div class="field__item"><a href="/tags/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tags/ie7" hreflang="en">IE7</a></div> <div class="field__item"><a href="/tags/ie8" hreflang="en">IE8</a></div> <div class="field__item"><a href="/tags/internet-explorer" hreflang="en">internet explorer</a></div> <div class="field__item"><a href="/tags/sass" hreflang="en">Sass</a></div> <div class="field__item"><a href="/tags/theming" hreflang="en">Theming</a></div> <div class="field__item"><a href="/tags/web-design" hreflang="en">web design</a></div> </div> </div> <div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="https://preview-misriptide.gtsb.io/blog/sass-breakpoint-mixin-meets-ie8"></iframe></div> Thu, 08 Aug 2013 14:56:01 +0000 Mediacurrent Team 918 at https://publish.mediacurrent.com