A place to cache linked articles (think custom and personal wayback machine)
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

vor 4 Jahren
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463
  1. title: Sass Guidelines
  2. url: http://sass-guidelin.es/
  3. hash_url: 92a7109f713f1c5643b393ef6f873427
  4. <h2 class="baseline">An opinionated styleguide for writing sane, maintainable and scalable Sass.</h2>
  5. <div class="translation-warning">
  6. <p>The Sass Guidelines project has been translated into several languages by <a target="_blank" href="https://github.com/HugoGiraudel/sass-guidelines/blob/gh-pages/_data/languages.yml">generous contributors</a>. Open the <button data-toggle="aside" class="link-like" role="button" type="button">options panel</button> to switch.</p>
  7. </div>
  8. <h1 id="about-the-author">About the author</h1>
  9. <p>My name is <a href="http://hugogiraudel.com">Hugo Giraudel</a>, I am a French front-end developer based in Berlin, Germany. I have been writing Sass for over two years now and am the author of Sass-related projects such as <a href="http://sassdoc.com">SassDoc</a> and <a href="http://sass-compatibility.github.io">Sass-Compatibility</a>. I also wrote a book about CSS (in French) entitled <a href="http://www.amazon.fr/dp/2212140231">CSS3 Pratique du Design Web</a>.</p>
  10. <p>I have also written a couple of Sass libraries, mostly for the heck of it: <a href="https://github.com/HugoGiraudel/SassyJSON">SassyJSON</a>, <a href="http://sassylists.com">SassyLists</a>, <a href="https://github.com/HugoGiraudel/SassySort">SassySort</a>, <a href="https://github.com/HugoGiraudel/SassyCast">SassyCast</a>, <a href="https://github.com/HugoGiraudel/SassyMatrix">SassyMatrix</a>, <a href="https://github.com/HugoGiraudel/SassyBitwise">SassyBitwise</a>, <a href="https://github.com/HugoGiraudel/SassyIteratorsGenerators">SassyIteratorsGenerators</a>, <a href="https://github.com/HugoGiraudel/SassyLogger">SassyLogger</a>, <a href="https://github.com/HugoGiraudel/SassyStrings">SassyStrings</a> and <a href="https://github.com/HugoGiraudel/SassyGradients">SassyGradients</a>.</p>
  11. <h1 id="contributing">Contributing</h1>
  12. <p>Sass Guidelines is a free project that I maintain in my spare time. Needless to say, it is quite a large amount of work to keep everything up-to-date, documented and relevant. Obviously, knowing that you liked this styleguide is already much appreciated!</p>
  13. <p>Now if you feel like contributing, please know that tweeting about it, spreading the word, or fixing a tiny typo by opening an issue or a pull-request on the <a href="https://github.com/HugoGiraudel/sass-guidelines">GitHub repository</a> would be great!</p>
  14. <p>Last but not least before we start: if you enjoyed this document, or if it is useful for you or your team, please consider supporting it!</p>
  15. <h1 id="table-of-contents">Table of Contents</h1>
  16. <h1 id="about-sass">About Sass</h1>
  17. <p>This is how <a href="http://sass-lang.com">Sass</a> describes itself in its <a href="http://sass-lang.com/documentation/file.SASS_REFERENCE.html">documentation</a>:</p>
  18. <blockquote>
  19. <p>Sass is an extension of CSS that adds power and elegance to the basic language.</p>
  20. </blockquote>
  21. <p>Sass’s ultimate objective is to fix CSS’s flaws. CSS, as we all know, is not the best language in the world <sup>[citation needed]</sup>. While very simple to learn, it can quickly get quite messy, especially on large projects.</p>
  22. <p>This is where Sass comes in, as a meta-language, to improve CSS’s syntax in order to provide extra features and handy tools. Meanwhile, Sass wants to be conservative regarding the CSS language.</p>
  23. <p>The point is not to turn CSS into a fully-featured programming language; Sass only wants to help where CSS fails. Because of this, getting started with Sass is no harder than learning CSS: it simply adds a couple of extra features on top of it.</p>
  24. <p>That being said, there are many ways to use these features. Some good, some bad, some unusual. These guidelines are meant to give you a consistent and documented approach to writing Sass code.</p>
  25. <h6 id="further-reading">Further reading</h6>
  26. <h2 id="ruby-sass-or-libsass">Ruby Sass or LibSass</h2>
  27. <p><a href="https://github.com/hcatlin/sass/commit/fa5048ba405619273e474a50400c7243fbff54fe">Sass’s first commit</a> goes back as far as late 2006, over 8 years ago. Needless to say it has come a long way since then. Initially developed in Ruby, varied ports popped up here and there. The most successful one, <a href="https://github.com/sass/libsass">LibSass</a> (written in C) is now close to being fully compatible with the original Ruby version.</p>
  28. <p>In 2014, <a href="https://github.com/sass/libsass/wiki/The-LibSass-Compatibility-Plan">Ruby Sass and LibSass teams decided to wait for both versions to sync up before moving forward</a>. Since then, LibSass has been actively releasing versions to have feature-parity with its older brother. The last remaining inconsistencies are gathered and listed by myself under the <a href="http://sass-compatibility.github.io">Sass-Compatibility</a> project. If you are aware of an incompatibility between the two versions that is not listed, please be kind enough to open an issue.</p>
  29. <p>Coming back to choosing your compiler. Actually, it all depends on your project. If it is a Ruby on Rails project, you better use Ruby Sass, which is perfectly suited for such a case. Also, be aware that Ruby Sass will always be the reference implementation and will always lead LibSass in features.</p>
  30. <p>On non-Ruby projects that need a workflow integration, LibSass is probably a better idea since it is mostly dedicated to being wrapped. So if you want to use, let’s say Node.js, <a href="https://github.com/sass/node-sass">node-sass</a> is all chosen.</p>
  31. <h6 id="further-reading-1">Further reading</h6>
  32. <h2 id="sass-or-scss">Sass or SCSS</h2>
  33. <p>There is quite a lot of confusion regarding the semantics of the name <em>Sass</em>, and for good reason: Sass means both the preprocessor and its own syntax. Not very convenient, is it?</p>
  34. <p>You see, Sass initially described a syntax of which the defining characteristic was its indentation-sensitivity. Soon enough, Sass maintainers decided to close the gap between Sass and CSS by providing a CSS-friendly syntax called <em>SCSS</em> for <em>Sassy CSS</em>. The motto is: if it’s valid CSS, it’s valid SCSS.</p>
  35. <p>Since then, Sass (the preprocessor) has been providing two different syntaxes: Sass (not all-caps, <a href="http://sassnotsass.com">please</a>), also known as <em>the indented syntax</em>, and SCSS. Which one to use is pretty much up to you since both are strictly equivalent in features. It’s only a matter of aesthetics at this point.</p>
  36. <p>Sass’s whitespace-sensitive syntax relies on indentation to get rid of braces, semi-colons and other punctuation symbols, leading to a leaner and shorter syntax. Meanwhile, SCSS is easier to learn since it’s mostly some tiny extra bits on top of CSS.</p>
  37. <p>I, myself, prefer SCSS over Sass because it is closer to CSS and friendlier to most developers. Because of that, SCSS is the default syntax throughout these guidelines. You can switch to Sass indented syntax in the <button data-toggle="aside" class="link-like" role="button" type="button">options panel</button>.</p>
  38. <h6 id="further-reading-2">Further reading</h6>
  39. <h2 id="other-preprocessors">Other preprocessors</h2>
  40. <p>Sass is a preprocessor among others. Its most serious competitor has to be <a href="http://lesscss.org/">LESS</a>, a Node.js based preprocessor that has gotten quite popular thanks to the famous CSS framework <a href="http://getbootstrap.com/">Bootstrap</a> using it. There is also <a href="http://learnboost.github.io/stylus/">Stylus</a> - which is kind of the nerdy, unrestricted version of LESS - where you can do pretty much whatever you want since it almost turns CSS into a programming language.</p>
  41. <p><em>Why choose Sass over LESS or another preprocessor?</em> is still a valid question today. Not so long ago, we used to recommend Sass for Ruby-based projects because it was first made in Ruby and played well with Ruby on Rails. Now that LibSass has caught up (mostly) with original Sass, this is no longer relevant advice.</p>
  42. <p>What I do like with Sass is its conservative approach to CSS. Sass’s design is based on strong principles: much of the design approach comes naturally out of the core teams’ beliefs that a) adding extra features has a complexity cost that needs to be justified by usefulness and, b) it should be easy to reason about what a given block of styles is doing by looking at that block alone. Also, Sass has a much sharper attention to detail than other preprocessors. As far as I can tell, the core designers care deeply about supporting every corner-case of CSS compatibility and making sure every general behavior is consistent.</p>
  43. <p>In other words, Sass is not a preprocessor aimed at pleasing nerdy wannabe programmers like me by adding extraordinary features on top of a language that is not intended to support any logical use-cases. It is a software aimed at solving actual issues; helping to provide useful functionality to CSS where CSS falls short.</p>
  44. <p>Preprocessors aside, we should also mention postprocessors, which have received significant exposure in the last few months, thanks mainly to <a href="https://github.com/postcss/postcss">PostCSS</a> and <a href="https://cssnext.github.io/">cssnext</a>. Postprocessors are pretty much equivalent to preprocessors except they do not provide anything else other than upcoming CSS syntax.</p>
  45. <p>You can think of postprocessors as a polyfill for unsupported CSS features. For instance, you would write variables as they are described in the <a href="http://dev.w3.org/csswg/css-variables/">CSS specifications</a>, then compile your stylesheets with a postprocessor only to find every variable occurrence gets replaced with its value, as Sass would do.</p>
  46. <p>The idea behind postprocessors is that once browsers support new features (e.g. CSS variables), the postprocessor does not compile them anymore and lets browsers take over.</p>
  47. <p>While providing tomorrow’s syntax today is something of a noble idea, I have to say I still prefer using Sass for most tasks. However, there are some occasions where I believe postprocessors are more suited than Sass and the like - CSS prefixing for instance - but we’ll get back to this.</p>
  48. <h6 id="further-reading-3">Further reading</h6>
  49. <h1 id="introduction">Introduction</h1>
  50. <h2 id="why-a-styleguide">Why a styleguide</h2>
  51. <p>A styleguide is not just a pleasing document to read, picturing an ideal state for your code. It is a key document in a project’s life, describing how and why code should be written. It may look like overkill for small projects, but it helps a lot in keeping the codebase clean, scalable and easily maintainable.</p>
  52. <p>Needless to say, the more developers involved on a project, the more code guidelines are needed. Along the same lines, the bigger the project, the more a styleguide is a must.</p>
  53. <p><a href="http://csswizardry.com">Harry Roberts</a> states it very well in <a href="http://cssguidelin.es/#the-importance-of-a-styleguide">CSS Guidelines</a>:</p>
  54. <blockquote>
  55. <p>A coding styleguide (note, not a visual styleguide) is a valuable tool for teams who:</p>
  56. <ul>
  57. <li>build and maintain products for a reasonable length of time;</li>
  58. <li>have developers of differing abilities and specialties;</li>
  59. <li>have a number of different developers working on a product at any given time;</li>
  60. <li>on-board new staff regularly;</li>
  61. <li>have a number of codebases that developers dip in and out of.</li>
  62. </ul>
  63. </blockquote>
  64. <h2 id="disclaimer">Disclaimer</h2>
  65. <p>First things first: <strong>this is not a CSS styleguide</strong>. This document will not discuss naming conventions for CSS classes, modular patterns and the question of IDs in the CSS world. These guidelines only aim at dealing with Sass-specific content.</p>
  66. <p>Also, this styleguide is my own and therefore <strong>very opinionated</strong>. Think of it as a collection of methodologies and advice that I have polished and given over the years. It also gives me the opportunity to link to a handful of insightful resources, so be sure to check the <em>further readings</em>.</p>
  67. <p>Obviously, this is certainly not the only way of doing things, and it may or may not suit your project. Feel free to pick from it and adapt it to your needs. As we say, <em>your mileage may vary</em>.</p>
  68. <h2 id="key-principles">Key principles</h2>
  69. <p>At the end of the day, if there is one thing I would like you to get from this whole styleguide, it is that <strong>Sass should be kept as simple as it can be</strong>.</p>
  70. <p>Thanks to my silly experiments like <a href="https://github.com/HugoGiraudel/SassyBitwise">bitwise operators</a>, <a href="https://github.com/HugoGiraudel/SassyIteratorsGenerators">iterators and generators</a> and <a href="https://github.com/HugoGiraudel/SassyJSON">a JSON parser</a> in Sass, we are all well aware of what one can do with this preprocessor.</p>
  71. <p>Meanwhile, CSS is a simple language. Sass, being intended to write CSS, should not get much more complex than regular CSS. The <a href="http://en.wikipedia.org/wiki/KISS_principle">KISS principle</a> (Keep It Simple Stupid) is key here and may even take precedence over the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY principle</a> (Don’t Repeat Yourself) in some circumstances.</p>
  72. <p>Sometimes, it’s better to repeat a little to keep the code maintainable, rather than building a top-heavy, unwieldy, unnecessarily complicated system that is completely unmaintainable because it is overly complex.</p>
  73. <p>Also, and let me quote <a href="https://csswizardry.com">Harry Roberts</a> once again, <strong>pragmatism trumps perfection</strong>. At some point, you will probably find yourself going against the rules described here. If it makes sense, if it feels right, do it. Code is just a means, not an end.</p>
  74. <h6 id="further-reading-4">Further reading</h6>
  75. <h1 id="syntax--formatting">Syntax &amp; formatting</h1>
  76. <p>If you ask me, the very first thing a styleguide should do is describe the way we want our code to look.</p>
  77. <p>When several developers are involved in writing CSS on the same project(s), it is only a matter of time before one of them starts doing things their own way. Code guidelines that promote consistency not only prevent this, but also help when it comes to reading and updating the code.</p>
  78. <p>Roughly, we want (shamelessly inspired by <a href="http://cssguidelin.es/#syntax-and-formatting">CSS Guidelines</a>):</p>
  79. <ul>
  80. <li>two (2) spaces indents, no tabs;</li>
  81. <li>ideally, 80-characters wide lines;</li>
  82. <li>properly written multi-line CSS rules;</li>
  83. <li>meaningful use of whitespace.</li>
  84. </ul>
  85. <div class="code-block">
  86. <div class="code-block__wrapper" data-syntax="scss">
  87. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  88. <span class="nc">.foo</span> <span class="p">{</span>
  89. <span class="na">display</span><span class="o">:</span> <span class="no">block</span><span class="p">;</span>
  90. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  91. <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">1</span><span class="kt">em</span><span class="p">;</span>
  92. <span class="p">}</span>
  93. <span class="c1">// Nope</span>
  94. <span class="nc">.foo</span> <span class="p">{</span>
  95. <span class="na">display</span><span class="o">:</span> <span class="no">block</span><span class="p">;</span> <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  96. <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">1</span><span class="kt">em</span><span class="p">;</span>
  97. <span class="p">}</span></code></pre></div>
  98. </div>
  99. <div class="code-block__wrapper" data-syntax="sass">
  100. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Since Sass indented-syntax forces those coding standards</span>
  101. <span class="c1">// There is no wrong way of proceeding</span>
  102. <span class="nc">.foo</span>
  103. <span class="na">display</span><span class="o">:</span> <span class="no">block</span>
  104. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  105. <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">1</span><span class="kt">em</span></code></pre></div>
  106. </div>
  107. </div>
  108. <p>We will not tackle the question of file organization in this section. It is the object of <a href="#architecture">another section</a>.</p>
  109. <h2 id="strings">Strings</h2>
  110. <p>Believe it or not, strings play quite a large role in both CSS and Sass ecosystems. Most CSS values are either lengths or strings (usually unquoted), so it actually is quite crucial to stick to some guidelines when dealing with strings in Sass.</p>
  111. <h3 id="encoding">Encoding</h3>
  112. <p>To avoid any potential issue with character encoding, it is highly recommended to force <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoding in the <a href="#main-file">main stylesheet</a> using the <code>@charset</code> directive. Make sure it is the very first element of the stylesheet and there is no character of any kind before it.</p>
  113. <h3 id="quotes">Quotes</h3>
  114. <p>CSS does not require strings to be quoted, not even those containing spaces. Take font-family names for instance: it doesn’t matter whether you wrap them in quotes for the CSS parser.</p>
  115. <p>Because of this, Sass <em>also</em> does not require strings to be quoted. Even better (and <em>luckily</em>, you’ll concede), a quoted string is strictly equivalent to its unquoted twin (e.g. <code>'abc'</code> is strictly equal to <code>abc</code>).</p>
  116. <p>That being said, languages that do not require strings to be quoted are definitely a minority and so, <strong>strings should always be wrapped with single quotes</strong> (<code>'</code>) in Sass (single being easier to type than double on <em>qwerty</em> keyboards). Besides consistency with other languages, including CSS’ cousin JavaScript, there are several reasons for this choice:</p>
  117. <ul>
  118. <li>color names are treated as colors when unquoted, which can lead to serious issues;</li>
  119. <li>most syntax highlighters will choke on unquoted strings;</li>
  120. <li>it helps general readability;</li>
  121. <li>there is no valid reason not to quote strings.</li>
  122. </ul>
  123. <div class="code-block">
  124. <div class="code-block__wrapper" data-syntax="scss">
  125. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  126. <span class="nv">$direction</span><span class="o">:</span> <span class="s1">'</span><span class="s2">left'</span><span class="p">;</span>
  127. <span class="c1">// Nope</span>
  128. <span class="nv">$direction</span><span class="o">:</span> <span class="no">left</span><span class="p">;</span></code></pre></div>
  129. </div>
  130. <div class="code-block__wrapper" data-syntax="sass">
  131. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  132. <span class="nv">$direction</span><span class="o">:</span> <span class="s1">'</span><span class="s2">left'</span>
  133. <span class="c1">// Nope</span>
  134. <span class="nv">$direction</span><span class="o">:</span> <span class="no">left</span></code></pre></div>
  135. </div>
  136. </div>
  137. <h3 id="strings-as-css-values">Strings as CSS values</h3>
  138. <p>Specific CSS values such as <code>initial</code> or <code>sans-serif</code> require not to be quoted. Indeed, the declaration <code>font-family: 'sans-serif'</code> will silently fail because CSS is expecting an identifier, not a quoted string. Because of this, we do not quote those values.</p>
  139. <div class="code-block">
  140. <div class="code-block__wrapper" data-syntax="scss">
  141. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  142. <span class="nv">$font-type</span><span class="o">:</span> <span class="no">sans-serif</span><span class="p">;</span>
  143. <span class="c1">// Nope</span>
  144. <span class="nv">$font-type</span><span class="o">:</span> <span class="s1">'</span><span class="s2">sans-serif'</span><span class="p">;</span>
  145. <span class="c1">// Okay I guess</span>
  146. <span class="nv">$font-type</span><span class="o">:</span> <span class="nf">unquote</span><span class="p">(</span><span class="s1">'</span><span class="s2">sans-serif'</span><span class="p">);</span></code></pre></div>
  147. </div>
  148. <div class="code-block__wrapper" data-syntax="sass">
  149. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  150. <span class="na">$font-type</span><span class="o">:</span> <span class="no">sans-serif</span>
  151. <span class="c1">// Nope</span>
  152. <span class="na">$font-type</span><span class="o">:</span> <span class="s1">'</span><span class="s2">sans-serif'</span>
  153. <span class="c1">// Okay I guess</span>
  154. <span class="na">$font-type</span><span class="o">:</span> <span class="nf">unquote</span><span class="p">(</span><span class="s1">'</span><span class="s2">sans-serif'</span><span class="p">)</span></code></pre></div>
  155. </div>
  156. </div>
  157. <p>Hence, we can make a distinction between strings intended to be used as CSS values (CSS identifiers) like in the previous example, and strings when sticking to the Sass data type, for instance map keys.</p>
  158. <p>We don’t quote the former, but we do wrap the latter in single quotes.</p>
  159. <h3 id="strings-containing-quotes">Strings containing quotes</h3>
  160. <p>If a string contains one or several single quotes, one might consider wrapping the string with double quotes (<code>"</code>) instead, in order to avoid escaping too many characters within the string.</p>
  161. <div class="code-block">
  162. <div class="code-block__wrapper" data-syntax="scss">
  163. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Okay</span>
  164. <span class="k">@warn</span> <span class="s1">'</span><span class="s2">You can\'t do that.'</span><span class="p">;</span>
  165. <span class="c1">// Okay</span>
  166. <span class="k">@warn</span> <span class="s2">"You can't do that."</span><span class="p">;</span></code></pre></div>
  167. </div>
  168. <div class="code-block__wrapper" data-syntax="sass">
  169. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Okay</span>
  170. <span class="k">@warn</span> <span class="s1">'</span><span class="s2">You can\'t do that.'</span>
  171. <span class="c1">// Okay</span>
  172. <span class="k">@warn</span> <span class="s2">"You can't do that."</span></code></pre></div>
  173. </div>
  174. </div>
  175. <h3 id="urls">URLs</h3>
  176. <p>URLs should be quoted as well, for the same reasons as above:</p>
  177. <div class="code-block">
  178. <div class="code-block__wrapper" data-syntax="scss">
  179. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  180. <span class="nc">.foo</span> <span class="p">{</span>
  181. <span class="na">background-image</span><span class="o">:</span> <span class="sx">url('/images/kittens.jpg')</span><span class="p">;</span>
  182. <span class="p">}</span>
  183. <span class="c1">// Nope</span>
  184. <span class="nc">.foo</span> <span class="p">{</span>
  185. <span class="na">background-image</span><span class="o">:</span> <span class="sx">url(/images/kittens.jpg)</span><span class="p">;</span>
  186. <span class="p">}</span></code></pre></div>
  187. </div>
  188. <div class="code-block__wrapper" data-syntax="sass">
  189. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  190. <span class="nc">.foo</span>
  191. <span class="na">background-image</span><span class="o">:</span> <span class="sx">url('/images/kittens.jpg')</span>
  192. <span class="c1">// Nope</span>
  193. <span class="nc">.foo</span>
  194. <span class="na">background-image</span><span class="o">:</span> <span class="sx">url(/images/kittens.jpg)</span></code></pre></div>
  195. </div>
  196. </div>
  197. <h6 id="further-reading-5">Further reading</h6>
  198. <h2 id="numbers">Numbers</h2>
  199. <p>In Sass, number is a data type including everything from unitless numbers to lengths, durations, frequencies, angles and so on. This allows calculations to be run on such measures.</p>
  200. <h3 id="zeros">Zeros</h3>
  201. <p>Numbers should display leading zeros before a decimal value less than one. Never display trailing zeros.</p>
  202. <div class="code-block">
  203. <div class="code-block__wrapper" data-syntax="scss">
  204. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  205. <span class="nc">.foo</span> <span class="p">{</span>
  206. <span class="na">padding</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span><span class="p">;</span>
  207. <span class="na">opacity</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.5</span><span class="p">;</span>
  208. <span class="p">}</span>
  209. <span class="c1">// Nope</span>
  210. <span class="nc">.foo</span> <span class="p">{</span>
  211. <span class="na">padding</span><span class="o">:</span> <span class="mi">2</span><span class="mf">.0</span><span class="kt">em</span><span class="p">;</span>
  212. <span class="na">opacity</span><span class="o">:</span> <span class="mf">.5</span><span class="p">;</span>
  213. <span class="p">}</span></code></pre></div>
  214. </div>
  215. <div class="code-block__wrapper" data-syntax="sass">
  216. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  217. <span class="nc">.foo</span>
  218. <span class="na">padding</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span>
  219. <span class="na">opacity</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.5</span>
  220. <span class="c1">// Nope</span>
  221. <span class="nc">.foo</span>
  222. <span class="na">padding</span><span class="o">:</span> <span class="mi">2</span><span class="mf">.0</span><span class="kt">em</span>
  223. <span class="na">opacity</span><span class="o">:</span> <span class="mf">.5</span></code></pre></div>
  224. </div>
  225. </div>
  226. <h3 id="units">Units</h3>
  227. <p>When dealing with lengths, a <code>0</code> value should never ever have a unit.</p>
  228. <div class="code-block">
  229. <div class="code-block__wrapper" data-syntax="scss">
  230. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  231. <span class="nv">$length</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  232. <span class="c1">// Nope</span>
  233. <span class="nv">$length</span><span class="o">:</span> <span class="mi">0</span><span class="kt">em</span><span class="p">;</span></code></pre></div>
  234. </div>
  235. <div class="code-block__wrapper" data-syntax="sass">
  236. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  237. <span class="nv">$length</span><span class="o">:</span> <span class="mi">0</span>
  238. <span class="c1">// Nope</span>
  239. <span class="nv">$length</span><span class="o">:</span> <span class="mi">0</span><span class="kt">em</span></code></pre></div>
  240. </div>
  241. </div>
  242. <p>The most common mistake I can think of regarding numbers in Sass, is thinking that units are just some strings that can be safely appended to a number. While that sounds true, it is certainly not how units work. Think of units as algebraic symbols. For instance, in the real world, multiplying 5 inches by 5 inches gives you 25 square inches. The same logic applies to Sass.</p>
  243. <p>To add a unit to a number, you have to multiply this number by <em>1 unit</em>.</p>
  244. <div class="code-block">
  245. <div class="code-block__wrapper" data-syntax="scss">
  246. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$value</span><span class="o">:</span> <span class="mi">42</span><span class="p">;</span>
  247. <span class="c1">// Yep</span>
  248. <span class="nv">$length</span><span class="o">:</span> <span class="nv">$value</span> <span class="o">*</span> <span class="mi">1</span><span class="kt">px</span><span class="p">;</span>
  249. <span class="c1">// Nope</span>
  250. <span class="nv">$length</span><span class="o">:</span> <span class="nv">$value</span> <span class="o">+</span> <span class="no">px</span><span class="p">;</span></code></pre></div>
  251. </div>
  252. <div class="code-block__wrapper" data-syntax="sass">
  253. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nv">$value</span><span class="o">:</span> <span class="mi">42</span>
  254. <span class="c1">// Yep</span>
  255. <span class="nv">$length</span><span class="o">:</span> <span class="nv">$value</span> <span class="o">*</span> <span class="mi">1</span><span class="kt">px</span>
  256. <span class="c1">// Nope</span>
  257. <span class="nv">$length</span><span class="o">:</span> <span class="nv">$value</span> <span class="o">+</span> <span class="no">px</span></code></pre></div>
  258. </div>
  259. </div>
  260. <p>Note that adding <em>0 member of that unit</em> also works, but I would rather recommend the aforementioned method since adding <em>0 unit</em> can be a bit confusing. Indeed, when trying to convert a number to another compatible unit, adding 0 will not do the trick.</p>
  261. <div class="code-block">
  262. <div class="code-block__wrapper" data-syntax="scss">
  263. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$value</span><span class="o">:</span> <span class="mi">42</span> <span class="o">+</span> <span class="mi">0</span><span class="kt">px</span><span class="p">;</span>
  264. <span class="c1">// -&gt; 42px</span>
  265. <span class="nv">$value</span><span class="o">:</span> <span class="mi">1</span><span class="kt">in</span> <span class="o">+</span> <span class="mi">0</span><span class="kt">px</span><span class="p">;</span>
  266. <span class="c1">// -&gt; 1in</span>
  267. <span class="nv">$value</span><span class="o">:</span> <span class="mi">0</span><span class="kt">px</span> <span class="o">+</span> <span class="mi">1</span><span class="kt">in</span><span class="p">;</span>
  268. <span class="c1">// -&gt; 96px</span></code></pre></div>
  269. </div>
  270. <div class="code-block__wrapper" data-syntax="sass">
  271. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nv">$value</span><span class="o">:</span> <span class="mi">42</span> <span class="o">+</span> <span class="mi">0</span><span class="kt">px</span>
  272. <span class="c1">// -&gt; 42px</span>
  273. <span class="nv">$value</span><span class="o">:</span> <span class="mi">1</span><span class="kt">in</span> <span class="o">+</span> <span class="mi">0</span><span class="kt">px</span>
  274. <span class="c1">// -&gt; 1in</span>
  275. <span class="nv">$value</span><span class="o">:</span> <span class="mi">0</span><span class="kt">px</span> <span class="o">+</span> <span class="mi">1</span><span class="kt">in</span>
  276. <span class="c1">// -&gt; 96px</span></code></pre></div>
  277. </div>
  278. </div>
  279. <p>In the end, it really depends on what you are trying to achieve. Just keep in mind that adding the unit as a string is not a good way to proceed.</p>
  280. <p>To remove the unit of a value, you have to divide it by <em>one unit of its kind</em>.</p>
  281. <div class="code-block">
  282. <div class="code-block__wrapper" data-syntax="scss">
  283. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$length</span><span class="o">:</span> <span class="mi">42</span><span class="kt">px</span><span class="p">;</span>
  284. <span class="c1">// Yep</span>
  285. <span class="nv">$value</span><span class="o">:</span> <span class="nv">$length</span> <span class="o">/</span> <span class="mi">1</span><span class="kt">px</span><span class="p">;</span>
  286. <span class="c1">// Nope</span>
  287. <span class="nv">$value</span><span class="o">:</span> <span class="nf">str-slice</span><span class="p">(</span><span class="nv">$length</span> <span class="o">+</span> <span class="nf">unquote</span><span class="p">(</span><span class="s1">'</span><span class="s2">'</span><span class="p">)</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="p">);</span></code></pre></div>
  288. </div>
  289. <div class="code-block__wrapper" data-syntax="sass">
  290. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nv">$length</span><span class="o">:</span> <span class="mi">42</span><span class="kt">px</span>
  291. <span class="c1">// Yep</span>
  292. <span class="nv">$value</span><span class="o">:</span> <span class="nv">$length</span> <span class="o">/</span> <span class="mi">1</span><span class="kt">px</span>
  293. <span class="c1">// Nope</span>
  294. <span class="nv">$value</span><span class="o">:</span> <span class="nf">str-slice</span><span class="p">(</span><span class="nv">$length</span> <span class="o">+</span> <span class="nf">unquote</span><span class="p">(</span><span class="s1">'</span><span class="s2">'</span><span class="p">)</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="p">)</span></code></pre></div>
  295. </div>
  296. </div>
  297. <p>Appending a unit as a string to a number results in a string, preventing any additional operation on the value. Slicing the numeric part of a number with a unit also results in a string. This is not what you want.</p>
  298. <h3 id="calculations">Calculations</h3>
  299. <p><strong>Top-level numeric calculations should always be wrapped in parentheses</strong>. Not only does this requirement dramatically improve readability, it also prevents some edge cases by forcing Sass to evaluate the contents of the parentheses.</p>
  300. <div class="code-block">
  301. <div class="code-block__wrapper" data-syntax="scss">
  302. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  303. <span class="nc">.foo</span> <span class="p">{</span>
  304. <span class="na">width</span><span class="o">:</span> <span class="p">(</span><span class="mi">100</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">3</span><span class="p">);</span>
  305. <span class="p">}</span>
  306. <span class="c1">// Nope</span>
  307. <span class="nc">.foo</span> <span class="p">{</span>
  308. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">3</span><span class="p">;</span>
  309. <span class="p">}</span></code></pre></div>
  310. </div>
  311. <div class="code-block__wrapper" data-syntax="sass">
  312. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  313. <span class="nc">.foo</span>
  314. <span class="na">width</span><span class="o">:</span> <span class="p">(</span><span class="mi">100</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">3</span><span class="p">)</span>
  315. <span class="c1">// Nope</span>
  316. <span class="nc">.foo</span>
  317. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">3</span></code></pre></div>
  318. </div>
  319. </div>
  320. <h3 id="magic-numbers">Magic numbers</h3>
  321. <p>“Magic number” is an <a href="http://en.wikipedia.org/wiki/Magic_number_(programming)#Unnamed_numerical_constants">old school programming</a> term for <em>unnamed numerical constant</em>. Basically, it’s just a random number that happens to <em>just work</em>™ yet is not tied to any logical explanation.</p>
  322. <p>Needless to say <strong>magic numbers are a plague and should be avoided at all costs</strong>. When you cannot manage to find a reasonable explanation for why a number works, add an extensive comment explaining how you got there and why you think it works. Admitting you don’t know why something works is still more helpful to the next developer than them having to figure out what’s going on from scratch.</p>
  323. <div class="code-block">
  324. <div class="code-block__wrapper" data-syntax="scss">
  325. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="cm">/**</span>
  326. <span class="cm"> * 1. Magic number. This value is the lowest I could find to align the top of</span>
  327. <span class="cm"> * `.foo` with its parent. Ideally, we should fix it properly.</span>
  328. <span class="cm"> */</span>
  329. <span class="nc">.foo</span> <span class="p">{</span>
  330. <span class="na">top</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.327</span><span class="kt">em</span><span class="p">;</span> <span class="cm">/* 1 */</span>
  331. <span class="p">}</span></code></pre></div>
  332. </div>
  333. <div class="code-block__wrapper" data-syntax="sass">
  334. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="cm">/**</span>
  335. <span class="cm">* 1. Magic number. This value is the lowest I could find to align the top of</span>
  336. <span class="cm">* `.foo` with its parent. Ideally, we should fix it properly.</span>
  337. <span class="cm">*/</span>
  338. <span class="nc">.foo</span>
  339. <span class="na">top</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.327</span><span class="kt">em</span> <span class="cm">/* 1 </span><span class="c">*/</span></code></pre></div>
  340. </div>
  341. </div>
  342. <h6 id="further-reading-6">Further reading</h6>
  343. <h2 id="colors">Colors</h2>
  344. <p>Colors occupy an important place in the CSS language. Naturally, Sass ends up being a valuable ally when it comes to manipulating colors, mostly by providing a handful of <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html">powerful functions</a>.</p>
  345. <h3 id="color-formats">Color formats</h3>
  346. <p>In order to make colors as simple as they can be, my advice would be to respect the following order of preference for color formats:</p>
  347. <ol>
  348. <li><a href="http://www.w3.org/TR/css3-color/#svg-color">CSS color keywords</a>;</li>
  349. <li><a href="http://en.wikipedia.org/wiki/HSL_and_HSV">HSL notation</a>;</li>
  350. <li><a href="http://en.wikipedia.org/wiki/RGB_color_model">RGB notation</a>;</li>
  351. <li>Hexadecimal notation. Preferably lowercase and shortened when possible.</li>
  352. </ol>
  353. <p>For starters, keywords often speak for themselves. The HSL representation is not only the easiest one for the human brain to comprehend<sup>[citation needed]</sup>, it also makes it easy for stylesheet authors to tweak the color by adjusting the hue, saturation and lightness individually. RGB still has the benefit of showing right away if the color is more of a blue, a green or a red but it does not make it easy to build a color from the three parts. Lastly, hexadecimal is close to indecipherable for the human mind.</p>
  354. <div class="code-block">
  355. <div class="code-block__wrapper" data-syntax="scss">
  356. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  357. <span class="nc">.foo</span> <span class="p">{</span>
  358. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  359. <span class="p">}</span>
  360. <span class="c1">// Nope</span>
  361. <span class="nc">.foo</span> <span class="p">{</span>
  362. <span class="na">color</span><span class="o">:</span> <span class="mh">#FF0000</span><span class="p">;</span>
  363. <span class="p">}</span></code></pre></div>
  364. </div>
  365. <div class="code-block__wrapper" data-syntax="sass">
  366. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  367. <span class="nc">.foo</span>
  368. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span>
  369. <span class="c1">// Nope</span>
  370. <span class="nc">.foo</span>
  371. <span class="na">color</span><span class="o">:</span> <span class="mh">#FF0000</span></code></pre></div>
  372. </div>
  373. </div>
  374. <p>When using HSL or RGB notation, always add a single space after a comma (<code>,</code>) and no space between parentheses (<code>(</code>, <code>)</code>) and content.</p>
  375. <div class="code-block">
  376. <div class="code-block__wrapper" data-syntax="scss">
  377. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  378. <span class="nc">.foo</span> <span class="p">{</span>
  379. <span class="na">color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="mf">.1</span><span class="p">);</span>
  380. <span class="na">background</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="p">);</span>
  381. <span class="p">}</span>
  382. <span class="c1">// Nope</span>
  383. <span class="nc">.foo</span> <span class="p">{</span>
  384. <span class="na">color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="mf">.1</span><span class="p">);</span>
  385. <span class="na">background</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span> <span class="mi">300</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span> <span class="p">);</span>
  386. <span class="p">}</span></code></pre></div>
  387. </div>
  388. <div class="code-block__wrapper" data-syntax="sass">
  389. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  390. <span class="nc">.foo</span>
  391. <span class="na">color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="mf">.1</span><span class="p">)</span>
  392. <span class="na">background</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="p">)</span>
  393. <span class="c1">// Nope</span>
  394. <span class="nc">.foo</span>
  395. <span class="na">color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="o">,</span><span class="mi">0</span><span class="mf">.1</span><span class="p">)</span>
  396. <span class="na">background</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span> <span class="mi">300</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span><span class="o">,</span> <span class="mi">100</span><span class="kt">%</span> <span class="p">)</span></code></pre></div>
  397. </div>
  398. </div>
  399. <h3 id="colors-and-variables">Colors and variables</h3>
  400. <p>When using a color more than once, store it in a variable with a meaningful name representing the color.</p>
  401. <p>Now you are free to use this variable wherever you want. However, if your usage is strongly tied to a theme, I would advise against using the variable as is. Instead, store it in another variable with a name explaining how it should be used.</p>
  402. <div class="code-block">
  403. <div class="code-block__wrapper" data-syntax="scss">
  404. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$main-theme-color</span><span class="o">:</span> <span class="nv">$sass-pink</span><span class="p">;</span></code></pre></div>
  405. </div>
  406. <div class="code-block__wrapper" data-syntax="sass">
  407. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="na">$main-theme-color</span><span class="o">:</span> <span class="nv">$sass-pink</span></code></pre></div>
  408. </div>
  409. </div>
  410. <p>Doing this would prevent a theme change leading to something like <code>$sass-pink: blue</code>.</p>
  411. <h3 id="lightening-and-darkening-colors">Lightening and darkening colors</h3>
  412. <p>Both <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#lighten-instance_method"><code>lighten</code></a> and <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#darken-instance_method"><code>darken</code></a> functions manipulate the lightness of a color in the HSL space by adding to or subtracting from the lightness in the HSL space. Basically, they are nothing but aliases for the <code>$lightness</code> parameter of the <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#adjust_color-instance_method"><code>adjust-color</code></a> function.</p>
  413. <p>The thing is, those functions often do not provide the expected result. On the other hand, the <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method"><code>mix</code></a> function is a nice way to lighten or darken a color by mixing it with either <code>white</code> or <code>black</code>.</p>
  414. <p>The benefit of using <code>mix</code> rather than one of the two aforementioned functions is that it will progressively go to black (or white) as you decrease the proportion of the color, whereas <code>darken</code> and <code>lighten</code> will quickly blow out a color all the way to black or white.</p>
  415. <figure role="group">
  416. <img alt="Illustration of the difference between lighten/darken and mix by KatieK&#10;" sizes="100vw" srcset="http://sass-guidelin.es/assets/images/lighten-darken-mix_small.png 540w,&#10; http://sass-guidelin.es/assets/images/lighten-darken-mix_medium.png 900w,&#10; http://sass-guidelin.es/assets/images/lighten-darken-mix_large.png 1200w,&#10; http://sass-guidelin.es/assets/images/lighten-darken-mix_huge.png 1590w"/>
  417. <figcaption><p>Illustration of the difference between <code>lighten</code>/<code>darken</code> and <code>mix</code> by <a href="http://codepen.io/KatieK2/pen/tejhz/">KatieK</a></p>
  418. </figcaption>
  419. </figure>
  420. <p>If you don’t want to write the <code>mix</code> function every time, you can create two easy-to-use functions <code>tint</code> and <code>shade</code> (which are also a part of <a href="http://compass-style.org/reference/compass/helpers/colors/#shade">Compass</a>) to do the same thing:</p>
  421. <div class="code-block">
  422. <div class="code-block__wrapper" data-syntax="scss">
  423. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Slightly lighten a color</span>
  424. <span class="c1">/// @access public</span>
  425. <span class="c1">/// @param {Color} $color - color to tint</span>
  426. <span class="c1">/// @param {Number} $percentage - percentage of `$color` in returned color</span>
  427. <span class="c1">/// @return {Color}</span>
  428. <span class="k">@function</span> <span class="nt">tint</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span> <span class="p">{</span>
  429. <span class="k">@return</span> <span class="nt">mix</span><span class="o">(</span><span class="nt">white</span><span class="o">,</span> <span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">);</span>
  430. <span class="p">}</span>
  431. <span class="c1">/// Slightly darken a color</span>
  432. <span class="c1">/// @access public</span>
  433. <span class="c1">/// @param {Color} $color - color to shade</span>
  434. <span class="c1">/// @param {Number} $percentage - percentage of `$color` in returned color</span>
  435. <span class="c1">/// @return {Color}</span>
  436. <span class="k">@function</span> <span class="nt">shade</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span> <span class="p">{</span>
  437. <span class="k">@return</span> <span class="nt">mix</span><span class="o">(</span><span class="nt">black</span><span class="o">,</span> <span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">);</span>
  438. <span class="p">}</span></code></pre></div>
  439. </div>
  440. <div class="code-block__wrapper" data-syntax="sass">
  441. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Slightly lighten a color</span>
  442. <span class="c1">/// @access public</span>
  443. <span class="c1">/// @param {Color} $color - color to tint</span>
  444. <span class="c1">/// @param {Number} $percentage - percentage of `$color` in returned color</span>
  445. <span class="c1">/// @return {Color}</span>
  446. <span class="k">@function</span> <span class="nt">tint</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span>
  447. <span class="k">@return</span> <span class="nt">mix</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="nt">white</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span>
  448. <span class="c1">/// Slightly darken a color</span>
  449. <span class="c1">/// @access public</span>
  450. <span class="c1">/// @param {Color} $color - color to shade</span>
  451. <span class="c1">/// @param {Number} $percentage - percentage of `$color` in returned color</span>
  452. <span class="c1">/// @return {Color}</span>
  453. <span class="k">@function</span> <span class="nt">shade</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span>
  454. <span class="k">@return</span> <span class="nt">mix</span><span class="o">(</span><span class="err">$</span><span class="nt">color</span><span class="o">,</span> <span class="nt">black</span><span class="o">,</span> <span class="err">$</span><span class="nt">percentage</span><span class="o">)</span></code></pre></div>
  455. </div>
  456. </div>
  457. <div class="note">
  458. <p>The <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#scale_color-instance_method"><code>scale-color</code></a> function is designed to scale properties more fluidly by taking into account how high or low they already are. It should provide results that are as nice as <code>mix</code>’s but with a clearer calling convention. The scaling factor isn’t exactly the same though.</p>
  459. </div>
  460. <h6 id="further-reading-7">Further reading</h6>
  461. <h2 id="lists">Lists</h2>
  462. <p>Lists are the Sass equivalent of arrays. A list is a flat data structure (unlike <a href="#maps">maps</a>) intended to store values of any type (including lists, leading to nested lists).</p>
  463. <p>Lists should respect the following guidelines:</p>
  464. <ul>
  465. <li>either inlined or multilines;</li>
  466. <li>necessarily on multilines if too long to fit on an 80-character line;</li>
  467. <li>unless used as is for CSS purposes, always comma separated;</li>
  468. <li>always wrapped in parenthesis;</li>
  469. <li>trailing comma if multilines, not if inlined.</li>
  470. </ul>
  471. <div class="code-block">
  472. <div class="code-block__wrapper" data-syntax="scss">
  473. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  474. <span class="nv">$font-stack</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span><span class="p">);</span>
  475. <span class="c1">// Yep</span>
  476. <span class="nv">$font-stack</span><span class="o">:</span> <span class="p">(</span>
  477. <span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span>
  478. <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span>
  479. <span class="no">sans-serif</span><span class="o">,</span>
  480. <span class="p">);</span>
  481. <span class="c1">// Nope</span>
  482. <span class="nv">$font-stack</span><span class="o">:</span> <span class="s1">'</span><span class="s2">Helvetica'</span> <span class="s1">'</span><span class="s2">Arial'</span> <span class="no">sans-serif</span><span class="p">;</span>
  483. <span class="c1">// Nope</span>
  484. <span class="nv">$font-stack</span><span class="o">:</span> <span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span><span class="p">;</span>
  485. <span class="c1">// Nope</span>
  486. <span class="nv">$font-stack</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span><span class="o">,</span><span class="p">);</span></code></pre></div>
  487. </div>
  488. <div class="code-block__wrapper" data-syntax="sass">
  489. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  490. <span class="na">$font-stack</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span><span class="p">)</span>
  491. <span class="c1">// Nope (not supported)</span>
  492. <span class="na">$font-stack</span><span class="o">:</span> <span class="p">(</span>
  493. <span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span>
  494. <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span>
  495. <span class="nt">sans-serif</span><span class="o">,</span>
  496. <span class="o">)</span>
  497. <span class="c1">// Nope</span>
  498. <span class="na">$font-stack</span><span class="o">:</span> <span class="s1">'</span><span class="s2">Helvetica'</span> <span class="s1">'</span><span class="s2">Arial'</span> <span class="no">sans-serif</span>
  499. <span class="c1">// Nope</span>
  500. <span class="na">$font-stack</span><span class="o">:</span> <span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span>
  501. <span class="c1">// Nope</span>
  502. <span class="na">$font-stack</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">Helvetica'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">Arial'</span><span class="o">,</span> <span class="no">sans-serif</span><span class="o">,</span><span class="p">)</span></code></pre></div>
  503. </div>
  504. </div>
  505. <p>When adding new items to a list, always use the provided API. Do not attempt to add new items manually.</p>
  506. <div class="code-block">
  507. <div class="code-block__wrapper" data-syntax="scss">
  508. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$shadows</span><span class="o">:</span> <span class="p">(</span><span class="mi">0</span> <span class="mi">42</span><span class="kt">px</span> <span class="mi">13</span><span class="mf">.37</span><span class="kt">px</span> <span class="ni">hotpink</span><span class="p">);</span>
  509. <span class="c1">// Yep</span>
  510. <span class="nv">$shadows</span><span class="o">:</span> <span class="nf">append</span><span class="p">(</span><span class="nv">$shadows</span><span class="o">,</span> <span class="nv">$shadow</span><span class="o">,</span> <span class="n">comma</span><span class="p">);</span>
  511. <span class="c1">// Nope</span>
  512. <span class="nv">$shadows</span><span class="o">:</span> <span class="nv">$shadows</span><span class="o">,</span> <span class="nv">$shadow</span><span class="p">;</span></code></pre></div>
  513. </div>
  514. <div class="code-block__wrapper" data-syntax="sass">
  515. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nv">$shadows</span><span class="o">:</span> <span class="p">(</span><span class="mi">0</span> <span class="mi">42</span><span class="kt">px</span> <span class="mi">13</span><span class="mf">.37</span><span class="kt">px</span> <span class="ni">hotpink</span><span class="p">)</span>
  516. <span class="c1">// Yep</span>
  517. <span class="nv">$shadows</span><span class="o">:</span> <span class="nf">append</span><span class="p">(</span><span class="nv">$shadows</span><span class="o">,</span> <span class="nv">$shadow</span><span class="o">,</span> <span class="n">comma</span><span class="p">)</span>
  518. <span class="c1">// Nope</span>
  519. <span class="nv">$shadows</span><span class="o">:</span> <span class="nv">$shadows</span><span class="o">,</span> <span class="nv">$shadow</span></code></pre></div>
  520. </div>
  521. </div>
  522. <h6 id="further-reading-8">Further reading</h6>
  523. <h2 id="maps">Maps</h2>
  524. <p>Since Sass 3.3, stylesheet authors can define maps — the Sass term for associative arrays, hashes or even JavaScript objects. A map is a data structure mapping keys (that can be any data type, including maps although I wouldn’t recommend it) to values of any type.</p>
  525. <p>Maps should be written as follows:</p>
  526. <ul>
  527. <li>space after the colon (<code>:</code>);</li>
  528. <li>opening brace (<code>(</code>) on the same line as the colon (<code>:</code>);</li>
  529. <li><strong>quoted keys</strong> if they are strings (which represents 99% of the cases);</li>
  530. <li>each key/value pair on its own new line;</li>
  531. <li>comma (<code>,</code>) at the end of each key/value;</li>
  532. <li><strong>trailing comma</strong> (<code>,</code>) on last item to make it easier to add, remove or reorder items;</li>
  533. <li>closing brace (<code>)</code>) on its own new line;</li>
  534. <li>no space or new line between closing brace (<code>)</code>) and semi-colon (<code>;</code>).</li>
  535. </ul>
  536. <p>Illustration:</p>
  537. <div class="code-block">
  538. <div class="code-block__wrapper" data-syntax="scss">
  539. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  540. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span>
  541. <span class="s1">'</span><span class="s2">small'</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span>
  542. <span class="s1">'</span><span class="s2">medium'</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span>
  543. <span class="s1">'</span><span class="s2">large'</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="o">,</span>
  544. <span class="p">);</span>
  545. <span class="c1">// Nope</span>
  546. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span> <span class="n">small</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span> <span class="no">medium</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span> <span class="no">large</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span> <span class="p">);</span></code></pre></div>
  547. </div>
  548. <div class="code-block__wrapper" data-syntax="sass">
  549. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  550. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">small'</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span> <span class="s1">'</span><span class="s2">medium'</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span> <span class="s1">'</span><span class="s2">large'</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="o">,</span><span class="p">)</span>
  551. <span class="c1">// Nope</span>
  552. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span> <span class="s1">'</span><span class="s2">small'</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span> <span class="s1">'</span><span class="s2">medium'</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span> <span class="s1">'</span><span class="s2">large'</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span> <span class="p">)</span>
  553. <span class="c1">// Nope</span>
  554. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span><span class="n">small</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span> <span class="no">medium</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span> <span class="no">large</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="o">,</span><span class="p">)</span>
  555. <span class="c1">// Nope (since it is not supported)</span>
  556. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span>
  557. <span class="na">'small'</span><span class="o">:</span> <span class="mi">767</span><span class="kt">px</span><span class="o">,</span>
  558. <span class="na">'medium'</span><span class="o">:</span> <span class="mi">992</span><span class="kt">px</span><span class="o">,</span>
  559. <span class="na">'large'</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="o">,</span>
  560. <span class="o">)</span></code></pre></div>
  561. </div>
  562. </div>
  563. <h3 id="debugging-a-sass-map">Debugging a Sass map</h3>
  564. <p>If you ever find yourself lost, wondering what kind of crazy magic is happening in a Sass map, worry not because there is still a way to be saved.</p>
  565. <div class="code-block">
  566. <div class="code-block__wrapper" data-syntax="scss">
  567. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@mixin</span><span class="nf"> debug-map</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span> <span class="p">{</span>
  568. <span class="k">@at-root</span> <span class="p">{</span>
  569. <span class="k">@debug</span><span class="o">-</span><span class="n">map</span> <span class="p">{</span>
  570. <span class="na">__toString__</span><span class="o">:</span> <span class="nf">inspect</span><span class="p">(</span><span class="nv">$map</span><span class="p">);</span>
  571. <span class="na">__length__</span><span class="o">:</span> <span class="nf">length</span><span class="p">(</span><span class="nv">$map</span><span class="p">);</span>
  572. <span class="na">__depth__</span><span class="o">:</span> <span class="nf">if</span><span class="p">(</span><span class="nf">function-exists</span><span class="p">(</span><span class="s1">'</span><span class="s2">map-depth'</span><span class="p">)</span><span class="o">,</span> <span class="nf">map-depth</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span><span class="o">,</span> <span class="n">null</span><span class="p">);</span>
  573. <span class="na">__keys__</span><span class="o">:</span> <span class="nf">map-keys</span><span class="p">(</span><span class="nv">$map</span><span class="p">);</span>
  574. <span class="nt">__properties__</span> <span class="p">{</span>
  575. <span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span> <span class="p">{</span>
  576. <span class="nn">#</span><span class="p">{</span><span class="s1">'</span><span class="s2">('</span> <span class="o">+</span> <span class="nt">type-of</span><span class="o">(</span><span class="err">$</span><span class="nt">value</span><span class="o">)</span> <span class="o">+</span> <span class="s1">'</span><span class="s2">) '</span> <span class="o">+</span> <span class="err">$</span><span class="nt">key</span><span class="p">}</span><span class="nd">:</span> <span class="nt">inspect</span><span class="o">(</span><span class="err">$</span><span class="nt">value</span><span class="o">);</span>
  577. <span class="p">}</span>
  578. <span class="p">}</span>
  579. <span class="p">}</span>
  580. <span class="p">}</span>
  581. <span class="p">}</span></code></pre></div>
  582. </div>
  583. <div class="code-block__wrapper" data-syntax="sass">
  584. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nf">=debug-map</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span>
  585. <span class="k">@at-root</span>
  586. <span class="k">@debug</span><span class="o">-</span><span class="n">map</span>
  587. <span class="na">__toString__</span><span class="o">:</span> <span class="nf">inspect</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span>
  588. <span class="na">__length__</span><span class="o">:</span> <span class="nf">length</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span>
  589. <span class="na">__depth__</span><span class="o">:</span> <span class="nf">if</span><span class="p">(</span><span class="nf">function-exists</span><span class="p">(</span><span class="s1">'</span><span class="s2">map-depth'</span><span class="p">)</span><span class="o">,</span> <span class="nf">map-depth</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span><span class="o">,</span> <span class="n">null</span><span class="p">)</span>
  590. <span class="na">__keys__</span><span class="o">:</span> <span class="nf">map-keys</span><span class="p">(</span><span class="nv">$map</span><span class="p">)</span>
  591. <span class="nt">__properties__</span>
  592. <span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span>
  593. <span class="na">#{'('</span><span class="err"> </span><span class="na">+</span><span class="err"> </span><span class="na">type-of($value)</span><span class="err"> </span><span class="na">+</span><span class="err"> </span><span class="na">')</span><span class="err"> </span><span class="na">'</span><span class="err"> </span><span class="na">+</span><span class="err"> </span><span class="na">$key}</span><span class="o">:</span> <span class="nf">inspect</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span></code></pre></div>
  594. </div>
  595. </div>
  596. <p>If you are interested in knowing the depth of the map, add the following function. The mixin will display it automatically.</p>
  597. <div class="code-block">
  598. <div class="code-block__wrapper" data-syntax="scss">
  599. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Compute the maximum depth of a map</span>
  600. <span class="c1">/// @param {Map} $map</span>
  601. <span class="c1">/// @return {Number} max depth of `$map`</span>
  602. <span class="k">@function</span> <span class="nt">map-depth</span><span class="o">(</span><span class="err">$</span><span class="nt">map</span><span class="o">)</span> <span class="p">{</span>
  603. <span class="nv">$level</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
  604. <span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span> <span class="p">{</span>
  605. <span class="k">@if</span> <span class="nf">type-of</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'</span><span class="s2">map'</span> <span class="p">{</span>
  606. <span class="nv">$level</span><span class="o">:</span> <span class="nf">max</span><span class="p">(</span><span class="nf">map-depth</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="o">,</span> <span class="nv">$level</span><span class="p">);</span>
  607. <span class="p">}</span>
  608. <span class="p">}</span>
  609. <span class="k">@return</span> <span class="err">$</span><span class="nt">level</span><span class="o">;</span>
  610. <span class="p">}</span></code></pre></div>
  611. </div>
  612. <div class="code-block__wrapper" data-syntax="sass">
  613. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Compute the maximum depth of a map</span>
  614. <span class="c1">/// @param {Map} $map</span>
  615. <span class="c1">/// @return {Number} max depth of `$map`</span>
  616. <span class="k">@function</span> <span class="nt">map-depth</span><span class="o">(</span><span class="err">$</span><span class="nt">map</span><span class="o">)</span>
  617. <span class="nv">$level</span><span class="o">:</span> <span class="mi">1</span>
  618. <span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span>
  619. <span class="k">@if</span> <span class="nf">type-of</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'</span><span class="s2">map'</span>
  620. <span class="nv">$level</span><span class="o">:</span> <span class="nf">max</span><span class="p">(</span><span class="nf">map-depth</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="o">,</span> <span class="nv">$level</span><span class="p">)</span>
  621. <span class="k">@return</span> <span class="err">$</span><span class="nt">level</span><span class="o">;</span></code></pre></div>
  622. </div>
  623. </div>
  624. <h6 id="further-reading-9">Further reading</h6>
  625. <h2 id="css-ruleset">CSS Ruleset</h2>
  626. <p>At this point, this is mostly revising what everybody knows, but here is how a CSS ruleset should be written (at least, according to most guidelines, including <a href="http://cssguidelin.es/#anatomy-of-a-ruleset">CSS Guidelines</a>):</p>
  627. <ul>
  628. <li>related selectors on the same line; unrelated selectors on new lines;</li>
  629. <li>the opening brace (<code>{</code>) spaced from the last selector by a single space;</li>
  630. <li>each declaration on its own new line;</li>
  631. <li>a space after the colon (<code>:</code>);</li>
  632. <li>a trailing semi-colon (<code>;</code>) at the end of all declarations;</li>
  633. <li>the closing brace (<code>}</code>) on its own new line;</li>
  634. <li>a new line after the closing brace <code>}</code>.</li>
  635. </ul>
  636. <p>Illustration:</p>
  637. <div class="code-block">
  638. <div class="code-block__wrapper" data-syntax="scss">
  639. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  640. <span class="nc">.foo</span><span class="o">,</span> <span class="nc">.foo-bar</span><span class="o">,</span>
  641. <span class="nc">.baz</span> <span class="p">{</span>
  642. <span class="na">display</span><span class="o">:</span> <span class="no">block</span><span class="p">;</span>
  643. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  644. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span><span class="p">;</span>
  645. <span class="p">}</span>
  646. <span class="c1">// Nope</span>
  647. <span class="nc">.foo</span><span class="o">,</span>
  648. <span class="nc">.foo-bar</span><span class="o">,</span> <span class="nc">.baz</span> <span class="p">{</span>
  649. <span class="na">display</span><span class="o">:</span> <span class="no">block</span><span class="p">;</span>
  650. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  651. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span> <span class="p">}</span></code></pre></div>
  652. </div>
  653. <div class="code-block__wrapper" data-syntax="sass">
  654. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  655. <span class="nc">.foo</span><span class="o">,</span> <span class="nc">.foo-bar</span><span class="o">,</span>
  656. <span class="nc">.baz</span>
  657. <span class="na">display</span><span class="o">:</span> <span class="no">block</span>
  658. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  659. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span>
  660. <span class="c1">// Nope</span>
  661. <span class="nc">.foo</span><span class="o">,</span>
  662. <span class="nc">.foo-bar</span><span class="o">,</span> <span class="nc">.baz</span>
  663. <span class="na">display</span><span class="o">:</span> <span class="no">block</span>
  664. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  665. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span></code></pre></div>
  666. </div>
  667. </div>
  668. <p>Adding to those CSS-related guidelines, we want to pay attention to:</p>
  669. <ul>
  670. <li>local variables being declared before any declarations, then spaced from declarations by a new line;</li>
  671. <li>mixin calls with no <code>@content</code> coming before any declaration;</li>
  672. <li>nested selectors always coming after a new line;</li>
  673. <li>mixin calls with <code>@content</code> coming after any nested selector;</li>
  674. <li>no new line before a closing brace (<code>}</code>).</li>
  675. </ul>
  676. <p>Illustration:</p>
  677. <div class="code-block">
  678. <div class="code-block__wrapper" data-syntax="scss">
  679. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span><span class="o">,</span> <span class="nc">.foo-bar</span><span class="o">,</span>
  680. <span class="nc">.baz</span> <span class="p">{</span>
  681. <span class="nv">$length</span><span class="o">:</span> <span class="mi">42</span><span class="kt">em</span><span class="p">;</span>
  682. <span class="k">@include</span><span class="nd"> ellipsis</span><span class="p">;</span>
  683. <span class="k">@include</span><span class="nd"> size</span><span class="p">(</span><span class="nv">$length</span><span class="p">);</span>
  684. <span class="na">display</span><span class="o">:</span> <span class="no">block</span><span class="p">;</span>
  685. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  686. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span><span class="p">;</span>
  687. <span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
  688. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  689. <span class="p">}</span>
  690. <span class="k">@include</span><span class="nd"> respond-to</span><span class="p">(</span><span class="s1">'</span><span class="s2">small'</span><span class="p">)</span> <span class="p">{</span>
  691. <span class="na">overflow</span><span class="o">:</span> <span class="no">visible</span><span class="p">;</span>
  692. <span class="p">}</span>
  693. <span class="p">}</span></code></pre></div>
  694. </div>
  695. <div class="code-block__wrapper" data-syntax="sass">
  696. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span><span class="o">,</span> <span class="nc">.foo-bar</span><span class="o">,</span>
  697. <span class="nc">.baz</span>
  698. <span class="nv">$length</span><span class="o">:</span> <span class="mi">42</span><span class="kt">em</span>
  699. <span class="nd">+ellipsis</span>
  700. <span class="nd">+size</span><span class="p">(</span><span class="nv">$length</span><span class="p">)</span>
  701. <span class="na">display</span><span class="o">:</span> <span class="no">block</span>
  702. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  703. <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span> <span class="no">auto</span>
  704. <span class="k">&amp;</span><span class="nd">:hover</span>
  705. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span>
  706. <span class="nd">+respond-to</span><span class="p">(</span><span class="s1">'</span><span class="s2">small'</span><span class="p">)</span>
  707. <span class="na">overflow</span><span class="o">:</span> <span class="no">visible</span></code></pre></div>
  708. </div>
  709. </div>
  710. <h6 id="further-reading-10">Further reading</h6>
  711. <h2 id="declaration-sorting">Declaration Sorting</h2>
  712. <p>I cannot think of many topics where opinions are as divided as they are regarding declaration sorting in CSS. Concretely, there are two factions here:</p>
  713. <ul>
  714. <li>sticking to the alphabetical order;</li>
  715. <li>ordering declarations by type (position, display, colors, font, miscellaneous…).</li>
  716. </ul>
  717. <p>There are pros and cons for both ways. On one hand, alphabetical order is universal (at least for languages using the latin alphabet) so there is no argument about sorting one property before another. However, it seems extremely weird to me to see properties such as <code>bottom</code> and <code>top</code> not right next to each other. Why would animations should appear before the display type? There are a lot of oddities with alphabetical ordering.</p>
  718. <div class="code-block">
  719. <div class="code-block__wrapper" data-syntax="scss">
  720. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  721. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span><span class="p">;</span>
  722. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  723. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span><span class="p">;</span>
  724. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span><span class="p">;</span>
  725. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span><span class="p">;</span>
  726. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  727. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  728. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span><span class="p">;</span>
  729. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  730. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  731. <span class="p">}</span></code></pre></div>
  732. </div>
  733. <div class="code-block__wrapper" data-syntax="sass">
  734. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  735. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span>
  736. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span>
  737. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span>
  738. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span>
  739. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span>
  740. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span>
  741. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  742. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span>
  743. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span>
  744. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span></code></pre></div>
  745. </div>
  746. </div>
  747. <p>On the other hand, ordering properties by type makes perfect sense. Every font-related declarations are gathered, <code>top</code> and <code>bottom</code> are reunited and reading a ruleset kind of feels like reading a short story. But unless you stick to some conventions like <a href="https://github.com/necolas/idiomatic-css">Idiomatic CSS</a>, there is a lot of room for interpretation in this way of doing things. Where would <code>white-space</code> go: font or display? Where does belong <code>overflow</code> exactly? What is the property order within a group (it could be alphabetically, oh the irony)?</p>
  748. <div class="code-block">
  749. <div class="code-block__wrapper" data-syntax="scss">
  750. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  751. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  752. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  753. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  754. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span><span class="p">;</span>
  755. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  756. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  757. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span><span class="p">;</span>
  758. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span><span class="p">;</span>
  759. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span><span class="p">;</span>
  760. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span><span class="p">;</span>
  761. <span class="p">}</span></code></pre></div>
  762. </div>
  763. <div class="code-block__wrapper" data-syntax="sass">
  764. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  765. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span>
  766. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span>
  767. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  768. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span>
  769. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span>
  770. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span>
  771. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span>
  772. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span>
  773. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span>
  774. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span></code></pre></div>
  775. </div>
  776. </div>
  777. <p>There is also another interesting subtree of type ordering called <a href="https://github.com/brandon-rhodes/Concentric-CSS">Concentric CSS</a>, that seems to be quite popular as well. Basically, Concentric CSS relies on the box-model to define an order: starts outside, moves inward.</p>
  778. <div class="code-block">
  779. <div class="code-block__wrapper" data-syntax="scss">
  780. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  781. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  782. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
  783. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span><span class="p">;</span>
  784. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  785. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
  786. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span><span class="p">;</span>
  787. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  788. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span><span class="p">;</span>
  789. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span><span class="p">;</span>
  790. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span><span class="p">;</span>
  791. <span class="p">}</span></code></pre></div>
  792. </div>
  793. <div class="code-block__wrapper" data-syntax="sass">
  794. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  795. <span class="na">width</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span>
  796. <span class="na">height</span><span class="o">:</span> <span class="mi">100</span><span class="kt">px</span>
  797. <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span>
  798. <span class="na">right</span><span class="o">:</span> <span class="mi">0</span>
  799. <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span>
  800. <span class="na">background</span><span class="o">:</span> <span class="nb">black</span>
  801. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span>
  802. <span class="na">color</span><span class="o">:</span> <span class="nb">white</span>
  803. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span>
  804. <span class="na">font-size</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">em</span></code></pre></div>
  805. </div>
  806. </div>
  807. <p>I must say I cannot decide myself. A <a href="http://css-tricks.com/poll-results-how-do-you-order-your-css-properties/">recent poll on CSS-Tricks</a> determined that over 45% developers order their declarations by type against 14% alphabetically. Also, there are 39% that go full random, including myself.</p>
  808. <figure role="group">
  809. <img src="http://sass-guidelin.es/assets/images/css-order-chart.png" alt="Chart showing how developers order their CSS declarations&#10;"/>
  810. <figcaption><p>Chart showing how developers order their CSS declarations</p>
  811. </figcaption>
  812. </figure>
  813. <p>Because of this, I will not impose a choice in this styleguide. Pick the one you prefer, as long as you are consistent throughout your stylesheets (i.e. not the <em>random</em> option).</p>
  814. <div class="note">
  815. <p>A <a href="http://peteschuster.com/2014/12/reduce-file-size-css-sorting/">recent study</a> shows that using <a href="https://github.com/csscomb/csscomb.js">CSS Comb</a> (which uses <a href="https://github.com/csscomb/csscomb.js/blob/master/config/csscomb.json">type ordering</a>) for sorting CSS declarations ends up shortening the average file size under Gzip compression by 2.7%, compared to 1.3% when sorting alphabetically.</p>
  816. </div>
  817. <h6 id="further-reading-11">Further reading</h6>
  818. <h2 id="selector-nesting">Selector Nesting</h2>
  819. <p>One particular feature Sass provides that is being overly misused by many developers is <em>selector nesting</em>. Selector nesting offers a way for stylesheet authors to compute long selectors by nesting shorter selectors within each others.</p>
  820. <h3 id="general-rule">General rule</h3>
  821. <p>For instance, the following Sass nesting:</p>
  822. <div class="code-block">
  823. <div class="code-block__wrapper" data-syntax="scss">
  824. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  825. <span class="nc">.bar</span> <span class="p">{</span>
  826. <span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
  827. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  828. <span class="p">}</span>
  829. <span class="p">}</span>
  830. <span class="p">}</span></code></pre></div>
  831. </div>
  832. <div class="code-block__wrapper" data-syntax="sass">
  833. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  834. <span class="nc">.bar</span>
  835. <span class="k">&amp;</span><span class="nd">:hover</span>
  836. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span></code></pre></div>
  837. </div>
  838. </div>
  839. <p>… will generate this CSS:</p>
  840. <div>
  841. <div class="highlight"><pre><code class="language-css" data-lang="css"><span class="nc">.foo</span> <span class="nc">.bar</span><span class="nd">:hover</span> <span class="p">{</span>
  842. <span class="k">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  843. <span class="p">}</span></code></pre></div>
  844. </div>
  845. <p>Along the same lines, since Sass 3.3 it is possible to use the current selector reference (<code>&amp;</code>) to generate advanced selectors. For instance:</p>
  846. <div class="code-block">
  847. <div class="code-block__wrapper" data-syntax="scss">
  848. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  849. <span class="k">&amp;</span><span class="nt">-bar</span> <span class="p">{</span>
  850. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  851. <span class="p">}</span>
  852. <span class="p">}</span></code></pre></div>
  853. </div>
  854. </div>
  855. <p>… will generate this CSS:</p>
  856. <p>This method is often used along with <a href="http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/">BEM naming conventions</a> to generate <code>.block__element</code> and <code>.block--modifier</code> selectors based on the original selector (i.e. <code>.block</code> in this case).</p>
  857. <div class="note">
  858. <p>While it might be anecdotal, generating new selectors from the current selector reference (<code>&amp;</code>) makes those selectors unsearchable in the codebase since they do not exist per se.</p>
  859. </div>
  860. <p>The problem with selector nesting is that it ultimately makes code more difficult to read. One has to mentally compute the resulting selector out of the indentation levels; it is not always quite obvious what the CSS will end up being.</p>
  861. <p>This statement becomes truer as selectors get longer and references to the current selector (<code>&amp;</code>) more frequent. At some point, the risk of losing track and not being able to understand what’s going on anymore is so high that it is not worth it.</p>
  862. <p>To prevent such a situation, we <strong>avoid selector nesting as much as possible</strong>. However, there are obviously a few exceptions to this rule.</p>
  863. <h3 id="exceptions">Exceptions</h3>
  864. <p>For starters, it is allowed and even recommended to nest pseudo-classes and pseudo-elements within the initial selector.</p>
  865. <div class="code-block">
  866. <div class="code-block__wrapper" data-syntax="scss">
  867. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  868. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  869. <span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
  870. <span class="na">color</span><span class="o">:</span> <span class="nb">green</span><span class="p">;</span>
  871. <span class="p">}</span>
  872. <span class="na">&amp;</span><span class="o">::</span><span class="n">before</span> <span class="p">{</span>
  873. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">pseudo-element'</span><span class="p">;</span>
  874. <span class="p">}</span>
  875. <span class="p">}</span></code></pre></div>
  876. </div>
  877. <div class="code-block__wrapper" data-syntax="sass">
  878. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  879. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span>
  880. <span class="k">&amp;</span><span class="nd">:hover</span>
  881. <span class="na">color</span><span class="o">:</span> <span class="nb">green</span>
  882. <span class="na">&amp;</span><span class="o">::</span><span class="n">before</span>
  883. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">pseudo-element'</span></code></pre></div>
  884. </div>
  885. </div>
  886. <p>Using selector nesting for pseudo-classes and pseudo-elements not only makes sense (because it deals with closely related selectors), it also helps keep everything about a component at the same place.</p>
  887. <p>Also, when using component-agnostic state classes such as <code>.is-active</code>, it is perfectly fine to nest it under the component’s selector to keep things tidy.</p>
  888. <div class="code-block">
  889. <div class="code-block__wrapper" data-syntax="scss">
  890. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  891. <span class="c1">// ...</span>
  892. <span class="k">&amp;</span><span class="nc">.is-active</span> <span class="p">{</span>
  893. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span><span class="p">;</span>
  894. <span class="p">}</span>
  895. <span class="p">}</span></code></pre></div>
  896. </div>
  897. <div class="code-block__wrapper" data-syntax="sass">
  898. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  899. <span class="c1">// ...</span>
  900. <span class="k">&amp;</span><span class="nc">.is-active</span>
  901. <span class="na">font-weight</span><span class="o">:</span> <span class="no">bold</span></code></pre></div>
  902. </div>
  903. </div>
  904. <p>Last but not least, when styling an element because it happens to be contained within another specific element, it is also fine to use nesting to keep everything about the component at the same place.</p>
  905. <div class="code-block">
  906. <div class="code-block__wrapper" data-syntax="scss">
  907. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  908. <span class="c1">// ...</span>
  909. <span class="nc">.no-opacity</span> <span class="k">&amp;</span> <span class="p">{</span>
  910. <span class="na">display</span><span class="o">:</span> <span class="no">none</span><span class="p">;</span>
  911. <span class="p">}</span>
  912. <span class="p">}</span></code></pre></div>
  913. </div>
  914. <div class="code-block__wrapper" data-syntax="sass">
  915. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  916. <span class="c1">// ...</span>
  917. <span class="nc">.no-opacity</span> <span class="k">&amp;</span>
  918. <span class="na">display</span><span class="o">:</span> <span class="no">none</span></code></pre></div>
  919. </div>
  920. </div>
  921. <p>When working with unexperienced developers, a selector such as <code>.no-opacity &amp;</code> might look a little weird. To prevent any confusion, you can build a very short mixin that transform this odd syntax into an explicit API.</p>
  922. <div class="code-block">
  923. <div class="code-block__wrapper" data-syntax="scss">
  924. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Helper mixin to provide simple API to selector nesting</span>
  925. <span class="c1">/// @param {String} $selector - Selector</span>
  926. <span class="k">@mixin</span><span class="nf"> when-inside</span><span class="p">(</span><span class="nv">$selector</span><span class="p">)</span> <span class="p">{</span>
  927. <span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">selector</span><span class="p">}</span> <span class="k">&amp;</span> <span class="p">{</span>
  928. <span class="k">@content</span><span class="o">;</span>
  929. <span class="p">}</span>
  930. <span class="p">}</span></code></pre></div>
  931. </div>
  932. <div class="code-block__wrapper" data-syntax="sass">
  933. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Helper mixin to provide simple API to selector nesting</span>
  934. <span class="c1">/// @param {String} $selector - Selector</span>
  935. <span class="nf">=when-inside</span><span class="p">(</span><span class="nv">$selector</span><span class="p">)</span> <span class="err">{</span>
  936. <span class="nn">#</span><span class="err">{$</span><span class="nt">selector</span><span class="err">}</span> <span class="k">&amp;</span>
  937. <span class="k">@content</span>
  938. <span class="err">}</span></code></pre></div>
  939. </div>
  940. </div>
  941. <p>Rewriting our previous example, it would look like this:</p>
  942. <div class="code-block">
  943. <div class="code-block__wrapper" data-syntax="scss">
  944. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  945. <span class="c1">// ...</span>
  946. <span class="k">@include</span><span class="nd"> when-inside</span><span class="p">(</span><span class="s1">'</span><span class="s2">.no-opacity'</span><span class="p">)</span> <span class="p">{</span>
  947. <span class="na">display</span><span class="o">:</span> <span class="no">none</span><span class="p">;</span>
  948. <span class="p">}</span>
  949. <span class="p">}</span></code></pre></div>
  950. </div>
  951. <div class="code-block__wrapper" data-syntax="sass">
  952. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  953. <span class="c1">// ...</span>
  954. <span class="nd">+when-inside</span><span class="p">(</span><span class="s1">'</span><span class="s2">.no-opacity'</span><span class="p">)</span>
  955. <span class="na">display</span><span class="o">:</span> <span class="no">none</span></code></pre></div>
  956. </div>
  957. </div>
  958. <p>As with everything, the specifics are somewhat irrelevant, consistency is key. If you feel fully confident with selector nesting, then use selector nesting. Just make sure your whole team is okay with that.</p>
  959. <h6 id="further-reading-12">Further reading</h6>
  960. <h1 id="naming-conventions">Naming conventions</h1>
  961. <p>In this section, we will not deal with the best CSS naming conventions for maintainability and scale; not only is that up to you, it’s also out of the scope of a Sass styleguide. I suggest those recommended by <a href="http://cssguidelin.es/#naming-conventions">CSS Guidelines</a>.</p>
  962. <p>There are a few things you can name in Sass, and it is important to name them well so the whole code base looks both consistent and easy to read:</p>
  963. <ul>
  964. <li>variables;</li>
  965. <li>functions;</li>
  966. <li>mixins.</li>
  967. </ul>
  968. <p>Sass placeholders are deliberately omitted from this list since they can be considered as regular CSS selectors, thus following the same naming pattern as classes.</p>
  969. <p>Regarding variables, functions and mixins, we stick to something very <em>CSS-y</em>: <strong>lowercase hyphen-delimited</strong>, and above all meaningful.</p>
  970. <div class="code-block">
  971. <div class="code-block__wrapper" data-syntax="scss">
  972. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$vertical-rhythm-baseline</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">rem</span><span class="p">;</span>
  973. <span class="k">@mixin</span><span class="nf"> size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span> <span class="p">{</span>
  974. <span class="c1">// ...</span>
  975. <span class="p">}</span>
  976. <span class="k">@function</span> <span class="nt">opposite-direction</span><span class="o">(</span><span class="err">$</span><span class="nt">direction</span><span class="o">)</span> <span class="p">{</span>
  977. <span class="c1">// ...</span>
  978. <span class="p">}</span></code></pre></div>
  979. </div>
  980. <div class="code-block__wrapper" data-syntax="sass">
  981. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="na">$vertical-rhythm-baseline</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">rem</span>
  982. <span class="nf">=size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span>
  983. <span class="c1">// ...</span>
  984. <span class="k">@function</span> <span class="nt">opposite-direction</span><span class="o">(</span><span class="err">$</span><span class="nt">direction</span><span class="o">)</span>
  985. <span class="c1">// ...</span></code></pre></div>
  986. </div>
  987. </div>
  988. <h6 id="further-reading-13">Further reading</h6>
  989. <h2 id="constants">Constants</h2>
  990. <p>If you happen to be a framework developer or library writer, you might find yourself dealing with variables that are not meant to be updated in any circumstances: constants. Unfortunately (or fortunately?), Sass does not provide any way to define such entities, so we have to stick to strict naming conventions to make our point.</p>
  991. <p>As for many languages, I suggest all-caps snakerized variables when they are constants. Not only is this a very old convention, but it also contrasts well with usual lowercased hyphenated variables.</p>
  992. <div class="code-block">
  993. <div class="code-block__wrapper" data-syntax="scss">
  994. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  995. <span class="nv">$CSS_POSITIONS</span><span class="o">:</span> <span class="p">(</span><span class="no">top</span><span class="o">,</span> <span class="no">right</span><span class="o">,</span> <span class="no">bottom</span><span class="o">,</span> <span class="no">left</span><span class="o">,</span> <span class="no">center</span><span class="p">);</span>
  996. <span class="c1">// Nope</span>
  997. <span class="nv">$css-positions</span><span class="o">:</span> <span class="p">(</span><span class="no">top</span><span class="o">,</span> <span class="no">right</span><span class="o">,</span> <span class="no">bottom</span><span class="o">,</span> <span class="no">left</span><span class="o">,</span> <span class="no">center</span><span class="p">);</span></code></pre></div>
  998. </div>
  999. <div class="code-block__wrapper" data-syntax="sass">
  1000. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  1001. <span class="nv">$CSS_POSITIONS</span><span class="o">:</span> <span class="p">(</span><span class="no">top</span><span class="o">,</span> <span class="no">right</span><span class="o">,</span> <span class="no">bottom</span><span class="o">,</span> <span class="no">left</span><span class="o">,</span> <span class="no">center</span><span class="p">)</span>
  1002. <span class="c1">// Nope</span>
  1003. <span class="na">$css-positions</span><span class="o">:</span> <span class="p">(</span><span class="no">top</span><span class="o">,</span> <span class="no">right</span><span class="o">,</span> <span class="no">bottom</span><span class="o">,</span> <span class="no">left</span><span class="o">,</span> <span class="no">center</span><span class="p">)</span></code></pre></div>
  1004. </div>
  1005. </div>
  1006. <h6 id="further-reading-14">Further reading</h6>
  1007. <h2 id="namespace">Namespace</h2>
  1008. <p>If you intend to distribute your Sass code, in the case of a library, a framework, a grid system or whatever, you might want to consider namespacing all your variables, functions, mixins and placeholders so it does not conflict with anyone else’s code.</p>
  1009. <p>For instance, if you work on a <em>Sassy Unicorn</em> project that is meant to be used by developers all over the world (who wouldn’t, right?), you could consider using <code>su-</code> as a namespace. It is specific enough to prevent any naming collisions and short enough not to be a pain to write.</p>
  1010. <div class="code-block">
  1011. <div class="code-block__wrapper" data-syntax="scss">
  1012. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$su-configuration</span><span class="o">:</span> <span class="p">(</span> <span class="o">...</span> <span class="p">);</span>
  1013. <span class="k">@function</span> <span class="nt">su-rainbow</span><span class="o">(</span><span class="err">$</span><span class="nt">unicorn</span><span class="o">)</span> <span class="p">{</span>
  1014. <span class="c1">// ...</span>
  1015. <span class="p">}</span></code></pre></div>
  1016. </div>
  1017. <div class="code-block__wrapper" data-syntax="sass">
  1018. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="na">$su-configuration</span><span class="o">:</span> <span class="p">(</span> <span class="o">...</span> <span class="p">)</span>
  1019. <span class="k">@function</span> <span class="nt">su-rainbow</span><span class="o">(</span><span class="err">$</span><span class="nt">unicorn</span><span class="o">)</span>
  1020. <span class="c1">// ...</span></code></pre></div>
  1021. </div>
  1022. </div>
  1023. <div class="note">
  1024. <p>Note that automatic namespacing is definitely a design goal for the upcoming <code>@import</code> revamp from Sass 4.0. As that comes closer to fruition, it will become less and less useful to do manual namespacing; eventually, manually-namespaced libraries may actually be harder to use.</p>
  1025. </div>
  1026. <h6 id="further-reading-15">Further reading</h6>
  1027. <p>CSS is a tricky language, full of hacks and oddities. Because of this, it should be heavily commented, especially if you or someone else intend to read and update the code 6 months or 1 year from now. Don’t let you or anybody else be in the position of <em>I-didn’t-write-this-oh-my-god-why</em>.</p>
  1028. <p>As simple as CSS can get, there is still a lot of room for comments. These could be explaining:</p>
  1029. <ul>
  1030. <li>the structure and/or role of a file;</li>
  1031. <li>the goal of a ruleset;</li>
  1032. <li>the idea behind a magic number;</li>
  1033. <li>the reason for a CSS declaration;</li>
  1034. <li>the order of CSS declarations;</li>
  1035. <li>the thought process behind a way of doing things.</li>
  1036. </ul>
  1037. <p>And I probably forgot a lot of other various reasons as well. Commenting takes very little time when done seamlessly along with the code so do it at the right time. Coming back at a piece of code to comment it is not only completely unrealistic but also extremely annoying.</p>
  1038. <p>Ideally, <em>any</em> CSS ruleset should be preceded by a C-style comment explaining the point of the CSS block. This comment also hosts numbered explanations regarding specific parts of the ruleset. For instance:</p>
  1039. <div class="code-block">
  1040. <div class="code-block__wrapper" data-syntax="scss">
  1041. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="cm">/**</span>
  1042. <span class="cm"> * Helper class to truncate and add ellipsis to a string too long for it to fit</span>
  1043. <span class="cm"> * on a single line.</span>
  1044. <span class="cm"> * 1. Prevent content from wrapping, forcing it on a single line.</span>
  1045. <span class="cm"> * 2. Add ellipsis at the end of the line.</span>
  1046. <span class="cm"> */</span>
  1047. <span class="nc">.ellipsis</span> <span class="p">{</span>
  1048. <span class="na">white-space</span><span class="o">:</span> <span class="no">nowrap</span><span class="p">;</span> <span class="cm">/* 1 */</span>
  1049. <span class="na">text-overflow</span><span class="o">:</span> <span class="n">ellipsis</span><span class="p">;</span> <span class="cm">/* 2 */</span>
  1050. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span><span class="p">;</span>
  1051. <span class="p">}</span></code></pre></div>
  1052. </div>
  1053. <div class="code-block__wrapper" data-syntax="sass">
  1054. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="cm">/**</span>
  1055. <span class="cm">* Helper class to truncate and add ellipsis to a string too long for it to fit</span>
  1056. <span class="cm">* on a single line.</span>
  1057. <span class="cm">* 1. Prevent content from wrapping, forcing it on a single line.</span>
  1058. <span class="cm">* 2. Add ellipsis at the end of the line.</span>
  1059. <span class="cm">*/</span>
  1060. <span class="nc">.ellipsis</span>
  1061. <span class="na">white-space</span><span class="o">:</span> <span class="no">nowrap</span> <span class="cm">/* 1 </span><span class="c">*/</span>
  1062. <span class="na">text-overflow</span><span class="o">:</span> <span class="n">ellipsis</span> <span class="cm">/* 2 </span><span class="c">*/</span>
  1063. <span class="na">overflow</span><span class="o">:</span> <span class="no">hidden</span></code></pre></div>
  1064. </div>
  1065. </div>
  1066. <p>Basically everything that is not obvious at first glance should be commented. There is no such thing as too much documentation. Remember that you cannot <em>comment too much</em>, so get on fire and write comments for everything that is worth it.</p>
  1067. <p>When commenting a Sass-specific section, use Sass inline comments instead of a C-style block. This makes the comment invisible in the output, even in expanded mode during development.</p>
  1068. <div class="code-block">
  1069. <div class="code-block__wrapper" data-syntax="scss">
  1070. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Add current module to the list of imported modules.</span>
  1071. <span class="c1">// `!global` flag is required so it actually updates the global variable.</span>
  1072. <span class="nv">$imported-modules</span><span class="o">:</span> <span class="nf">append</span><span class="p">(</span><span class="nv">$imported-modules</span><span class="o">,</span> <span class="nv">$module</span><span class="p">)</span> <span class="nv">!global</span><span class="p">;</span></code></pre></div>
  1073. </div>
  1074. <div class="code-block__wrapper" data-syntax="sass">
  1075. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Add current module to the list of imported modules.</span>
  1076. <span class="c1">// `!global` flag is required so it actually updates the global variable.</span>
  1077. <span class="na">$imported-modules</span><span class="o">:</span> <span class="nf">append</span><span class="p">(</span><span class="nv">$imported-modules</span><span class="o">,</span> <span class="nv">$module</span><span class="p">)</span> <span class="nv">!global</span></code></pre></div>
  1078. </div>
  1079. </div>
  1080. <h6 id="further-reading-16">Further reading</h6>
  1081. <h2 id="documentation">Documentation</h2>
  1082. <p>Every variable, function, mixin and placeholder that is intended to be reused all over the codebase should be documented as part of the global API using <a href="http://sassdoc.com">SassDoc</a>.</p>
  1083. <div class="code-block">
  1084. <div class="code-block__wrapper" data-syntax="scss">
  1085. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Vertical rhythm baseline used all over the code base.</span>
  1086. <span class="c1">/// @type Length</span>
  1087. <span class="nv">$vertical-rhythm-baseline</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">rem</span><span class="p">;</span></code></pre></div>
  1088. </div>
  1089. <div class="code-block__wrapper" data-syntax="sass">
  1090. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Vertical rhythm baseline used all over the code base.</span>
  1091. <span class="c1">/// @type Length</span>
  1092. <span class="na">$vertical-rhythm-baseline</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">rem</span></code></pre></div>
  1093. </div>
  1094. </div>
  1095. <div class="note">
  1096. <p>Three slashes (<code>/</code>) required.</p>
  1097. </div>
  1098. <p>SassDoc has two major roles:</p>
  1099. <ul>
  1100. <li>forcing standardized comments using an annotation-based system for everything that is part of a public or private API;</li>
  1101. <li>being able to generate an HTML version of the API documentation by using any of the SassDoc endpoints (CLI tool, Grunt, Gulp, Broccoli, Node…).</li>
  1102. </ul>
  1103. <figure role="group">
  1104. <img alt="Documentation generated by SassDoc&#10;" sizes="100vw" srcset="http://sass-guidelin.es/assets/images/sassdoc-preview_small.png 540w,&#10; http://sass-guidelin.es/assets/images/sassdoc-preview_medium.png 900w,&#10; http://sass-guidelin.es/assets/images/sassdoc-preview_large.png 1200w,&#10; http://sass-guidelin.es/assets/images/sassdoc-preview_huge.png 1590w"/>
  1105. <figcaption><p>Documentation generated by SassDoc</p>
  1106. </figcaption>
  1107. </figure>
  1108. <p>Here is an example of a mixin extensively documented with SassDoc:</p>
  1109. <div class="code-block">
  1110. <div class="code-block__wrapper" data-syntax="scss">
  1111. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Mixin helping defining both `width` and `height` simultaneously.</span>
  1112. <span class="c1">///</span>
  1113. <span class="c1">/// @author Hugo Giraudel</span>
  1114. <span class="c1">///</span>
  1115. <span class="c1">/// @access public</span>
  1116. <span class="c1">///</span>
  1117. <span class="c1">/// @param {Length} $width - Element’s `width`</span>
  1118. <span class="c1">/// @param {Length} $height ($width) - Element’s `height`</span>
  1119. <span class="c1">///</span>
  1120. <span class="c1">/// @example scss - Usage</span>
  1121. <span class="c1">/// .foo {</span>
  1122. <span class="c1">/// @include size(10em);</span>
  1123. <span class="c1">/// }</span>
  1124. <span class="c1">///</span>
  1125. <span class="c1">/// .bar {</span>
  1126. <span class="c1">/// @include size(100%, 10em);</span>
  1127. <span class="c1">/// }</span>
  1128. <span class="c1">///</span>
  1129. <span class="c1">/// @example css - CSS output</span>
  1130. <span class="c1">/// .foo {</span>
  1131. <span class="c1">/// width: 10em;</span>
  1132. <span class="c1">/// height: 10em;</span>
  1133. <span class="c1">/// }</span>
  1134. <span class="c1">///</span>
  1135. <span class="c1">/// .bar {</span>
  1136. <span class="c1">/// width: 100%;</span>
  1137. <span class="c1">/// height: 10em;</span>
  1138. <span class="c1">/// }</span>
  1139. <span class="k">@mixin</span><span class="nf"> size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span> <span class="p">{</span>
  1140. <span class="na">width</span><span class="o">:</span> <span class="nv">$width</span><span class="p">;</span>
  1141. <span class="na">height</span><span class="o">:</span> <span class="nv">$height</span><span class="p">;</span>
  1142. <span class="p">}</span></code></pre></div>
  1143. </div>
  1144. <div class="code-block__wrapper" data-syntax="sass">
  1145. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Mixin helping defining both `width` and `height` simultaneously.</span>
  1146. <span class="c1">///</span>
  1147. <span class="c1">/// @author Hugo Giraudel</span>
  1148. <span class="c1">///</span>
  1149. <span class="c1">/// @access public</span>
  1150. <span class="c1">///</span>
  1151. <span class="c1">/// @param {Length} $width - Element’s `width`</span>
  1152. <span class="c1">/// @param {Length} $height ($width) - Element’s `height`</span>
  1153. <span class="c1">///</span>
  1154. <span class="c1">/// @example scss - Usage</span>
  1155. <span class="c1">/// .foo</span>
  1156. <span class="c1">/// +size(10em)</span>
  1157. <span class="c1">///</span>
  1158. <span class="c1">/// .bar</span>
  1159. <span class="c1">/// +size(100%, 10em)</span>
  1160. <span class="c1">///</span>
  1161. <span class="c1">/// @example css - CSS output</span>
  1162. <span class="c1">/// .foo {</span>
  1163. <span class="c1">/// width: 10em;</span>
  1164. <span class="c1">/// height: 10em;</span>
  1165. <span class="c1">/// }</span>
  1166. <span class="c1">///</span>
  1167. <span class="c1">/// .bar {</span>
  1168. <span class="c1">/// width: 100%;</span>
  1169. <span class="c1">/// height: 10em;</span>
  1170. <span class="c1">/// }</span>
  1171. <span class="nf">=size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span>
  1172. <span class="na">width</span><span class="o">:</span> <span class="nv">$width</span>
  1173. <span class="na">height</span><span class="o">:</span> <span class="nv">$height</span></code></pre></div>
  1174. </div>
  1175. </div>
  1176. <h6 id="further-reading-17">Further reading</h6>
  1177. <h1 id="architecture">Architecture</h1>
  1178. <p>Architecting a CSS project is probably one of the most difficult things you will have to do in a project’s life. Keeping the architecture consistent and meaningful is even harder.</p>
  1179. <p>Fortunately, one of the main benefits of using a CSS preprocessor is having the ability to split the codebase over several files without impacting performance (like the <code>@import</code> CSS directive would do). Thanks to Sass’s overload of the <code>@import</code> directive, it is perfectly safe (and actually recommended) to use as many files as necessary in development, all compiled into a single stylesheet when going to production.</p>
  1180. <p>On top of that, I cannot stress enough the need for folders, even on small scale projects. At home, you don’t drop every sheet of paper into the same box. You use folders; one for the house/flat, one for the bank, one for bills, and so on. There is no reason to do otherwise when structuring a CSS project. Split the codebase into meaningful separated folders so it is easy to find stuff later when you have to come back to the code.</p>
  1181. <p>There are a lot of popular architectures for CSS projects: <a href="http://oocss.org/">OOCSS</a>, <a href="http://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a>, <a href="http://getbootstrap.com/">Bootstrap</a>-like, <a href="http://foundation.zurb.com/">Foundation</a>-like… They all have their merits, pros and cons.</p>
  1182. <p>I, myself, use an approach that happens to be quite similar to <a href="https://smacss.com/">SMACSS</a> from <a href="http://snook.ca/">Jonathan Snook</a>, which focuses on keeping things simple and obvious.</p>
  1183. <div class="note">
  1184. <p>I have learnt that architecture is most of the time very specific to the project. Feel free to discard completely or adapt the proposed solution so that you deal with a system that suits your needs.</p>
  1185. </div>
  1186. <h6 id="further-reading-18">Further reading</h6>
  1187. <h2 id="components">Components</h2>
  1188. <p>There is a major difference between making it <em>work</em>, and making it <em>good</em>. Again, CSS is quite a messy language <sup>[citation needed]</sup>. The less CSS we have, the merrier. We don’t want to deal with megabytes of CSS code. To keep stylesheets short and efficient—and this will not be any surprise to you—it is usually a good idea to think of an interface as a collection of components.</p>
  1189. <p>Components can be anything, as long as they:</p>
  1190. <ul>
  1191. <li>do one thing and one thing only;</li>
  1192. <li>are re-usable and re-used across the project;</li>
  1193. <li>are independent.</li>
  1194. </ul>
  1195. <p>For instance, a search form should be treated as a component. It should be reusable, at different positions, on different pages, in various situations. It should not depend on its position in the DOM (footer, sidebar, main content…).</p>
  1196. <p>Most of any interface can be thought of as little components and I highly recommend you stick to this paradigm. This will not only shorten the amount of CSS needed for the whole project, but also happens to be much easier to maintain than a chaotic mess where everything is flustered.</p>
  1197. <h2 id="the-7-1-pattern">The 7-1 pattern</h2>
  1198. <p>Back to architecture, shall we? I usually go with what I call the <em>7-1 pattern</em>: 7 folders, 1 file. Basically, you have all your partials stuffed into 7 different folders, and a single file at the root level (usually named <code>main.scss</code>) which imports them all to be compiled into a CSS stylesheet.</p>
  1199. <ul>
  1200. <li><code>base/</code></li>
  1201. <li><code>components/</code></li>
  1202. <li><code>layout/</code></li>
  1203. <li><code>pages/</code></li>
  1204. <li><code>themes/</code></li>
  1205. <li><code>utils/</code></li>
  1206. <li><code>vendors/</code></li>
  1207. </ul>
  1208. <p>And of course:</p>
  1209. <figure role="group">
  1210. <img alt="Wallpaper by Julien He&#10;" sizes="100vw" srcset="http://sass-guidelin.es/assets/images/sass-wallpaper_small.jpg 540w,&#10; http://sass-guidelin.es/assets/images/sass-wallpaper_medium.jpg 900w,&#10; http://sass-guidelin.es/assets/images/sass-wallpaper_large.jpg 1200w,&#10; http://sass-guidelin.es/assets/images/sass-wallpaper_huge.jpg 1590w"/>
  1211. <figcaption><p>Wallpaper by <a href="https://twitter.com/julien_he">Julien He</a></p>
  1212. </figcaption>
  1213. </figure>
  1214. <p>Ideally, we can come up with something like this:</p>
  1215. <div class="highlight"><pre><code>
  1216. sass/
  1217. |
  1218. |– base/
  1219. | |– _reset.scss # Reset/normalize
  1220. | |– _typography.scss # Typography rules
  1221. | ... # Etc…
  1222. |
  1223. |– components/
  1224. | |– _buttons.scss # Buttons
  1225. | |– _carousel.scss # Carousel
  1226. | |– _cover.scss # Cover
  1227. | |– _dropdown.scss # Dropdown
  1228. | ... # Etc…
  1229. |
  1230. |– layout/
  1231. | |– _navigation.scss # Navigation
  1232. | |– _grid.scss # Grid system
  1233. | |– _header.scss # Header
  1234. | |– _footer.scss # Footer
  1235. | |– _sidebar.scss # Sidebar
  1236. | |– _forms.scss # Forms
  1237. | ... # Etc…
  1238. |
  1239. |– pages/
  1240. | |– _home.scss # Home specific styles
  1241. | |– _contact.scss # Contact specific styles
  1242. | ... # Etc…
  1243. |
  1244. |– themes/
  1245. | |– _theme.scss # Default theme
  1246. | |– _admin.scss # Admin theme
  1247. | ... # Etc…
  1248. |
  1249. |– utils/
  1250. | |– _variables.scss # Sass Variables
  1251. | |– _functions.scss # Sass Functions
  1252. | |– _mixins.scss # Sass Mixins
  1253. | |– _helpers.scss # Class &amp; placeholders helpers
  1254. |
  1255. |– vendors/
  1256. | |– _bootstrap.scss # Bootstrap
  1257. | |– _jquery-ui.scss # jQuery UI
  1258. | ... # Etc…
  1259. |
  1260. |
  1261. `– main.scss # Main Sass file
  1262. </code></pre></div>
  1263. <div class="note">
  1264. <p>Files follow the same naming conventions described above: they are hyphen-delimited.</p>
  1265. </div>
  1266. <h3 id="base-folder">Base folder</h3>
  1267. <p>The <code>base/</code> folder holds what we might call the boilerplate code for the project. In there, you might find the reset file, some typographic rules, and probably a stylesheet (that I’m used to calling <code>_base.scss</code>), defining some standard styles for commonly used HTML elements.</p>
  1268. <ul>
  1269. <li><code>_base.scss</code></li>
  1270. <li><code>_reset.scss</code></li>
  1271. <li><code>_typography.scss</code></li>
  1272. </ul>
  1273. <h3 id="layout-folder">Layout folder</h3>
  1274. <p>The <code>layout/</code> folder contains everything that takes part in laying out the site or application. This folder could have stylesheets for the main parts of the site (header, footer, navigation, sidebar…), the grid system or even CSS styles for all the forms.</p>
  1275. <ul>
  1276. <li><code>_grid.scss</code></li>
  1277. <li><code>_header.scss</code></li>
  1278. <li><code>_footer.scss</code></li>
  1279. <li><code>_sidebar.scss</code></li>
  1280. <li><code>_forms.scss</code></li>
  1281. <li><code>_navigation.scss</code></li>
  1282. </ul>
  1283. <div class="note">
  1284. <p>The <code>layout/</code> folder might also be called <code>partials/</code>, depending on what you prefer.</p>
  1285. </div>
  1286. <h3 id="components-folder">Components folder</h3>
  1287. <p>For smaller components, there is the <code>components/</code> folder. While <code>layout/</code> is <em>macro</em> (defining the global wireframe), <code>components/</code> is more focused on widgets. It contains all kind of specific modules like a slider, a loader, a widget, and basically anything along those lines. There are usually a lot of files in <code>components/</code> since the whole site/application should be mostly composed of tiny modules.</p>
  1288. <ul>
  1289. <li><code>_media.scss</code></li>
  1290. <li><code>_carousel.scss</code></li>
  1291. <li><code>_thumbnails.scss</code></li>
  1292. </ul>
  1293. <div class="note">
  1294. <p>The <code>components/</code> folder might also be called <code>modules/</code>, depending on what you prefer.</p>
  1295. </div>
  1296. <h3 id="pages-folder">Pages folder</h3>
  1297. <p>If you have page-specific styles, it is better to put them in a <code>pages/</code> folder, in a file named after the page. For instance, it’s not uncommon to have very specific styles for the home page hence the need for a <code>_home.scss</code> file in <code>pages/</code>.</p>
  1298. <div class="note">
  1299. <p>Depending on your deployment process, these files could be called on their own to avoid merging them with the others in the resulting stylesheet. It is really up to you.</p>
  1300. </div>
  1301. <h3 id="themes-folder">Themes folder</h3>
  1302. <p>On large sites and applications, it is not unusual to have different themes. There are certainly different ways of dealing with themes but I personally like having them all in a <code>themes/</code> folder.</p>
  1303. <div class="note">
  1304. <p>This is very project-specific and is likely to be non-existent on many projects.</p>
  1305. </div>
  1306. <h3 id="utils-folder">Utils folder</h3>
  1307. <p>The <code>utils/</code> folder gathers all Sass tools and helpers used across the project. Every global variable, function, mixin and placeholder should be put in here.</p>
  1308. <p>The rule of thumb for this folder is that it should not output a single line of CSS when compiled on its own. These are nothing but Sass helpers.</p>
  1309. <ul>
  1310. <li><code>_variables.scss</code></li>
  1311. <li><code>_mixins.scss</code></li>
  1312. <li><code>_functions.scss</code></li>
  1313. <li><code>_placeholders.scss</code> (frequently named <code>_helpers.scss</code>)</li>
  1314. </ul>
  1315. <div class="note">
  1316. <p>The <code>utils/</code> folder might also be called <code>helpers/</code>, <code>sass-helpers/</code> or <code>sass-utils/</code>, depending on what you prefer.</p>
  1317. </div>
  1318. <h3 id="vendors-folder">Vendors folder</h3>
  1319. <p>And last but not least, most projects will have a <code>vendors/</code> folder containing all the CSS files from external libraries and frameworks – Normalize, Bootstrap, jQueryUI, FancyCarouselSliderjQueryPowered, and so on. Putting those aside in the same folder is a good way to say “Hey, this is not from me, not my code, not my responsibility”.</p>
  1320. <ul>
  1321. <li><code>_normalize.scss</code></li>
  1322. <li><code>_bootstrap.scss</code></li>
  1323. <li><code>_jquery-ui.scss</code></li>
  1324. <li><code>_select2.scss</code></li>
  1325. </ul>
  1326. <p>If you have to override a section of any vendor, I recommend you have an 8th folder called <code>vendors-extensions/</code> in which you may have files named exactly after the vendors they overwrite.</p>
  1327. <p>For instance, <code>vendors-extensions/_bootstrap.scss</code> is a file containing all CSS rules intended to re-declare some of Bootstrap’s default CSS. This is to avoid editing the vendor files themselves, which is generally not a good idea.</p>
  1328. <h3 id="main-file">Main file</h3>
  1329. <p>The main file (usually labelled <code>main.scss</code>) should be the only Sass file from the whole code base not to begin with an underscore. This file should not contain anything but <code>@import</code> and comments.</p>
  1330. <p>Files should be imported according to the folder they live in, one after the other in the following order:</p>
  1331. <ol>
  1332. <li><code>vendors/</code></li>
  1333. <li><code>utils/</code></li>
  1334. <li><code>base/</code></li>
  1335. <li><code>layout/</code></li>
  1336. <li><code>components/</code></li>
  1337. <li><code>pages/</code></li>
  1338. <li><code>themes/</code></li>
  1339. </ol>
  1340. <p>In order to preserve readability, the main file should respect these guidelines:</p>
  1341. <ul>
  1342. <li>one file per <code>@import</code>;</li>
  1343. <li>one <code>@import</code> per line;</li>
  1344. <li>no new line between two imports from the same folder;</li>
  1345. <li>a new line after the last import from a folder;</li>
  1346. <li>file extensions and leading underscores omitted.</li>
  1347. </ul>
  1348. <div class="code-block">
  1349. <div class="code-block__wrapper" data-syntax="scss">
  1350. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@import</span> <span class="s1">'</span><span class="s2">vendors/bootstrap'</span><span class="p">;</span>
  1351. <span class="k">@import</span> <span class="s1">'</span><span class="s2">vendors/jquery-ui'</span><span class="p">;</span>
  1352. <span class="k">@import</span> <span class="s1">'</span><span class="s2">utils/variables'</span><span class="p">;</span>
  1353. <span class="k">@import</span> <span class="s1">'</span><span class="s2">utils/functions'</span><span class="p">;</span>
  1354. <span class="k">@import</span> <span class="s1">'</span><span class="s2">utils/mixins'</span><span class="p">;</span>
  1355. <span class="k">@import</span> <span class="s1">'</span><span class="s2">utils/placeholders'</span><span class="p">;</span>
  1356. <span class="k">@import</span> <span class="s1">'</span><span class="s2">base/reset'</span><span class="p">;</span>
  1357. <span class="k">@import</span> <span class="s1">'</span><span class="s2">base/typography'</span><span class="p">;</span>
  1358. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/navigation'</span><span class="p">;</span>
  1359. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/grid'</span><span class="p">;</span>
  1360. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/header'</span><span class="p">;</span>
  1361. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/footer'</span><span class="p">;</span>
  1362. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/sidebar'</span><span class="p">;</span>
  1363. <span class="k">@import</span> <span class="s1">'</span><span class="s2">layout/forms'</span><span class="p">;</span>
  1364. <span class="k">@import</span> <span class="s1">'</span><span class="s2">components/buttons'</span><span class="p">;</span>
  1365. <span class="k">@import</span> <span class="s1">'</span><span class="s2">components/carousel'</span><span class="p">;</span>
  1366. <span class="k">@import</span> <span class="s1">'</span><span class="s2">components/cover'</span><span class="p">;</span>
  1367. <span class="k">@import</span> <span class="s1">'</span><span class="s2">components/dropdown'</span><span class="p">;</span>
  1368. <span class="k">@import</span> <span class="s1">'</span><span class="s2">pages/home'</span><span class="p">;</span>
  1369. <span class="k">@import</span> <span class="s1">'</span><span class="s2">pages/contact'</span><span class="p">;</span>
  1370. <span class="k">@import</span> <span class="s1">'</span><span class="s2">themes/theme'</span><span class="p">;</span>
  1371. <span class="k">@import</span> <span class="s1">'</span><span class="s2">themes/admin'</span><span class="p">;</span></code></pre></div>
  1372. </div>
  1373. <div class="code-block__wrapper" data-syntax="sass">
  1374. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@import</span> <span class="s">vendors/bootstrap</span>
  1375. <span class="k">@import</span> <span class="s">vendors/jquery-ui</span>
  1376. <span class="k">@import</span> <span class="s">utils/variables</span>
  1377. <span class="k">@import</span> <span class="s">utils/functions</span>
  1378. <span class="k">@import</span> <span class="s">utils/mixins</span>
  1379. <span class="k">@import</span> <span class="s">utils/placeholders</span>
  1380. <span class="k">@import</span> <span class="s">base/reset</span>
  1381. <span class="k">@import</span> <span class="s">base/typography</span>
  1382. <span class="k">@import</span> <span class="s">layout/navigation</span>
  1383. <span class="k">@import</span> <span class="s">layout/grid</span>
  1384. <span class="k">@import</span> <span class="s">layout/header</span>
  1385. <span class="k">@import</span> <span class="s">layout/footer</span>
  1386. <span class="k">@import</span> <span class="s">layout/sidebar</span>
  1387. <span class="k">@import</span> <span class="s">layout/forms</span>
  1388. <span class="k">@import</span> <span class="s">components/buttons</span>
  1389. <span class="k">@import</span> <span class="s">components/carousel</span>
  1390. <span class="k">@import</span> <span class="s">components/cover</span>
  1391. <span class="k">@import</span> <span class="s">components/dropdown</span>
  1392. <span class="k">@import</span> <span class="s">pages/home</span>
  1393. <span class="k">@import</span> <span class="s">pages/contact</span>
  1394. <span class="k">@import</span> <span class="s">themes/theme</span>
  1395. <span class="k">@import</span> <span class="s">themes/admin</span></code></pre></div>
  1396. </div>
  1397. </div>
  1398. <p>There is another way of importing partials that I deem valid as well. On the bright side, it makes the file more readable. On the other hand, it makes updating it slightly more painful. Anyway, I’ll let you decide which is best, it does not matter much. For this way of doing, the main file should respect these guidelines:</p>
  1399. <ul>
  1400. <li>one <code>@import</code> per folder;</li>
  1401. <li>a linebreak after <code>@import</code>;</li>
  1402. <li>each file on its own line;</li>
  1403. <li>a new line after the last import from a folder;</li>
  1404. <li>file extensions and leading underscores omitted.</li>
  1405. </ul>
  1406. <div class="code-block">
  1407. <div class="code-block__wrapper" data-syntax="scss">
  1408. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@import</span>
  1409. <span class="s1">'</span><span class="s2">vendors/bootstrap'</span><span class="o">,</span>
  1410. <span class="s1">'</span><span class="s2">vendors/jquery-ui'</span><span class="p">;</span>
  1411. <span class="k">@import</span>
  1412. <span class="s1">'</span><span class="s2">utils/variables'</span><span class="o">,</span>
  1413. <span class="s1">'</span><span class="s2">utils/functions'</span><span class="o">,</span>
  1414. <span class="s1">'</span><span class="s2">utils/mixins'</span><span class="o">,</span>
  1415. <span class="s1">'</span><span class="s2">utils/placeholders'</span><span class="p">;</span>
  1416. <span class="k">@import</span>
  1417. <span class="s1">'</span><span class="s2">base/reset'</span><span class="o">,</span>
  1418. <span class="s1">'</span><span class="s2">base/typography'</span><span class="p">;</span>
  1419. <span class="k">@import</span>
  1420. <span class="s1">'</span><span class="s2">layout/navigation'</span><span class="o">,</span>
  1421. <span class="s1">'</span><span class="s2">layout/grid'</span><span class="o">,</span>
  1422. <span class="s1">'</span><span class="s2">layout/header'</span><span class="o">,</span>
  1423. <span class="s1">'</span><span class="s2">layout/footer'</span><span class="o">,</span>
  1424. <span class="s1">'</span><span class="s2">layout/sidebar'</span><span class="o">,</span>
  1425. <span class="s1">'</span><span class="s2">layout/forms'</span><span class="p">;</span>
  1426. <span class="k">@import</span>
  1427. <span class="s1">'</span><span class="s2">components/buttons'</span><span class="o">,</span>
  1428. <span class="s1">'</span><span class="s2">components/carousel'</span><span class="o">,</span>
  1429. <span class="s1">'</span><span class="s2">components/cover'</span><span class="o">,</span>
  1430. <span class="s1">'</span><span class="s2">components/dropdown'</span><span class="p">;</span>
  1431. <span class="k">@import</span>
  1432. <span class="s1">'</span><span class="s2">pages/home'</span><span class="o">,</span>
  1433. <span class="s1">'</span><span class="s2">pages/contact'</span><span class="p">;</span>
  1434. <span class="k">@import</span>
  1435. <span class="s1">'</span><span class="s2">themes/theme'</span><span class="o">,</span>
  1436. <span class="s1">'</span><span class="s2">themes/admin'</span><span class="p">;</span></code></pre></div>
  1437. </div>
  1438. <div class="code-block__wrapper" data-syntax="sass">
  1439. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@import</span>
  1440. <span class="nt">vendors</span><span class="o">/</span><span class="nt">bootstrap</span><span class="o">,</span>
  1441. <span class="nt">vendors</span><span class="o">/</span><span class="nt">jquery-ui</span>
  1442. <span class="k">@import</span>
  1443. <span class="nt">utils</span><span class="o">/</span><span class="nt">variables</span><span class="o">,</span>
  1444. <span class="nt">utils</span><span class="o">/</span><span class="nt">functions</span><span class="o">,</span>
  1445. <span class="nt">utils</span><span class="o">/</span><span class="nt">mixins</span><span class="o">,</span>
  1446. <span class="nt">utils</span><span class="o">/</span><span class="nt">placeholders</span>
  1447. <span class="k">@import</span>
  1448. <span class="nt">base</span><span class="o">/</span><span class="nt">reset</span><span class="o">,</span>
  1449. <span class="nt">base</span><span class="o">/</span><span class="nt">typography</span>
  1450. <span class="k">@import</span>
  1451. <span class="nt">layout</span><span class="o">/</span><span class="nt">navigation</span><span class="o">,</span>
  1452. <span class="nt">layout</span><span class="o">/</span><span class="nt">grid</span><span class="o">,</span>
  1453. <span class="nt">layout</span><span class="o">/</span><span class="nt">header</span><span class="o">,</span>
  1454. <span class="nt">layout</span><span class="o">/</span><span class="nt">footer</span><span class="o">,</span>
  1455. <span class="nt">layout</span><span class="o">/</span><span class="nt">sidebar</span><span class="o">,</span>
  1456. <span class="nt">layout</span><span class="o">/</span><span class="nt">forms</span>
  1457. <span class="k">@import</span>
  1458. <span class="nt">components</span><span class="o">/</span><span class="nt">buttons</span><span class="o">,</span>
  1459. <span class="nt">components</span><span class="o">/</span><span class="nt">carousel</span><span class="o">,</span>
  1460. <span class="nt">components</span><span class="o">/</span><span class="nt">cover</span><span class="o">,</span>
  1461. <span class="nt">components</span><span class="o">/</span><span class="nt">dropdown</span>
  1462. <span class="k">@import</span>
  1463. <span class="nt">pages</span><span class="o">/</span><span class="nt">home</span><span class="o">,</span>
  1464. <span class="nt">pages</span><span class="o">/</span><span class="nt">contact</span>
  1465. <span class="k">@import</span>
  1466. <span class="nt">themes</span><span class="o">/</span><span class="nt">theme</span><span class="o">,</span>
  1467. <span class="nt">themes</span><span class="o">/</span><span class="nt">admin</span></code></pre></div>
  1468. </div>
  1469. </div>
  1470. <div class="note">
  1471. <p>In order to not have to import each file manually, there is an extension to Ruby Sass called <a href="https://github.com/chriseppstein/sass-globbing">sass-globbing</a>, making it possible to use glob patterns in Sass <code>@import</code> such as <code>@import "components/*"</code>.</p>
  1472. <p>That being said, I would not recommend it because it imports files following the alphabetical order which is usually not what you want, especially when dealing with a source-order dependent language.</p>
  1473. </div>
  1474. <h2 id="shame-file">Shame file</h2>
  1475. <p>There is an interesting concept that has been made popular by <a href="http://csswizardry.com">Harry Roberts</a>, <a href="http://daverupert.com">Dave Rupert</a> and <a href="http://css-tricks.com">Chris Coyier</a> that consists of putting all the CSS declarations, hacks and things we are not proud of in a <em>shame file</em>. This file, dramatically titled <code>_shame.scss</code>, would be imported after any other file, at the very end of the stylesheet.</p>
  1476. <div class="code-block">
  1477. <div class="code-block__wrapper" data-syntax="scss">
  1478. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="cm">/**</span>
  1479. <span class="cm"> * Nav specificity fix.</span>
  1480. <span class="cm"> *</span>
  1481. <span class="cm"> * Someone used an ID in the header code (`#header a {}`) which trumps the</span>
  1482. <span class="cm"> * nav selectors (`.site-nav a {}`). Use !important to override it until I</span>
  1483. <span class="cm"> * have time to refactor the header stuff.</span>
  1484. <span class="cm"> */</span>
  1485. <span class="nc">.site-nav</span> <span class="nt">a</span> <span class="p">{</span>
  1486. <span class="na">color</span><span class="o">:</span> <span class="mh">#BADA55</span> <span class="nv">!important</span><span class="p">;</span>
  1487. <span class="p">}</span></code></pre></div>
  1488. </div>
  1489. <div class="code-block__wrapper" data-syntax="sass">
  1490. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="cm">/**</span>
  1491. <span class="cm">* Nav specificity fix.</span>
  1492. <span class="cm">*</span>
  1493. <span class="cm">* Someone used an ID in the header code (`#header a {}`) which trumps the</span>
  1494. <span class="cm">* nav selectors (`.site-nav a {}`). Use !important to override it until I</span>
  1495. <span class="cm">* have time to refactor the header stuff.</span>
  1496. <span class="cm">*/</span>
  1497. <span class="nc">.site-nav</span> <span class="nt">a</span>
  1498. <span class="na">color</span><span class="o">:</span> <span class="mh">#BADA55</span> <span class="nv">!important</span></code></pre></div>
  1499. </div>
  1500. </div>
  1501. <h6 id="further-reading-19">Further reading</h6>
  1502. <h1 id="responsive-web-design-and-breakpoints">Responsive Web Design and breakpoints</h1>
  1503. <p>I do not think we still have to introduce Responsive Web Design now that it is everywhere. However you might ask yourself <em>why is there a section about RWD in a Sass styleguide?</em> Actually there are quite a few things that can be done to make working with breakpoints easier, so I thought it would not be such a bad idea to list them here.</p>
  1504. <h2 id="naming-breakpoints">Naming breakpoints</h2>
  1505. <p>I think it is safe to say that media queries should not be tied to specific devices. For instance, this is definitely a bad idea to try targeting iPads or Blackberry phones specifically. Media queries should take care of a range of screen sizes, until the design breaks and the next media query takes over.</p>
  1506. <p>For the same reasons, breakpoints should not be named after devices but something more general. Especially since some phones are now bigger than tablets, some tablets bigger than some tiny screen computers, and so on…</p>
  1507. <div class="code-block">
  1508. <div class="code-block__wrapper" data-syntax="scss">
  1509. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  1510. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span>
  1511. <span class="s1">'</span><span class="s2">medium'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1512. <span class="s1">'</span><span class="s2">large'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1513. <span class="s1">'</span><span class="s2">huge'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1514. <span class="p">);</span>
  1515. <span class="c1">// Nope</span>
  1516. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span>
  1517. <span class="s1">'</span><span class="s2">tablet'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1518. <span class="s1">'</span><span class="s2">computer'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1519. <span class="s1">'</span><span class="s2">tv'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1520. <span class="p">);</span></code></pre></div>
  1521. </div>
  1522. <div class="code-block__wrapper" data-syntax="sass">
  1523. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  1524. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">medium'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">large'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">huge'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">))</span>
  1525. <span class="c1">// Nope</span>
  1526. <span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">tablet'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">computer'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">tv'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">))</span></code></pre></div>
  1527. </div>
  1528. </div>
  1529. <p>At this point, any naming convention that makes crystal clear that a design is not intimately tied to a specific device type will do the trick, as long as it gives a sense of magnitude.</p>
  1530. <div class="code-block">
  1531. <div class="code-block__wrapper" data-syntax="scss">
  1532. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span>
  1533. <span class="s1">'</span><span class="s2">seed'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1534. <span class="s1">'</span><span class="s2">sprout'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1535. <span class="s1">'</span><span class="s2">plant'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span>
  1536. <span class="p">);</span></code></pre></div>
  1537. </div>
  1538. <div class="code-block__wrapper" data-syntax="sass">
  1539. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nv">$breakpoints</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">seed'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">800</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">sprout'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1000</span><span class="kt">px</span><span class="p">)</span><span class="o">,</span> <span class="s1">'</span><span class="s2">plant'</span><span class="o">:</span> <span class="p">(</span><span class="no">min-width</span><span class="o">:</span> <span class="mi">1200</span><span class="kt">px</span><span class="p">))</span></code></pre></div>
  1540. </div>
  1541. </div>
  1542. <div class="note">
  1543. <p>The previous examples uses nested maps to define breakpoints, however this really depends on what kind of breakpoint manager you use. You could opt for strings rather than inner maps for more flexibility (e.g. <code>'(min-width: 800px)'</code>).</p>
  1544. </div>
  1545. <h6 id="further-reading-20">Further reading</h6>
  1546. <h2 id="breakpoint-manager">Breakpoint manager</h2>
  1547. <p>Once you have named your breakpoints the way you want, you need a way to use them in actual media queries. There are plenty of ways to do so but I must say I am a big fan of the breakpoint map read by a getter function. This system is both simple and efficient.</p>
  1548. <div class="code-block">
  1549. <div class="code-block__wrapper" data-syntax="scss">
  1550. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Responsive manager.</span>
  1551. <span class="c1">/// @access public</span>
  1552. <span class="c1">/// @param {String} $breakpoint - Breakpoint</span>
  1553. <span class="c1">/// @requires $breakpoints</span>
  1554. <span class="k">@mixin</span><span class="nf"> respond-to</span><span class="p">(</span><span class="nv">$breakpoint</span><span class="p">)</span> <span class="p">{</span>
  1555. <span class="nv">$raw-query</span><span class="o">:</span> <span class="nf">map-get</span><span class="p">(</span><span class="nv">$breakpoints</span><span class="o">,</span> <span class="nv">$breakpoint</span><span class="p">);</span>
  1556. <span class="k">@if</span> <span class="nv">$raw-query</span> <span class="p">{</span>
  1557. <span class="nv">$query</span><span class="o">:</span> <span class="nf">if</span><span class="p">(</span><span class="nf">type-of</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'</span><span class="s2">string'</span><span class="o">,</span> <span class="nf">unquote</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">)</span><span class="o">,</span> <span class="nf">inspect</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">));</span>
  1558. <span class="k">@media</span> <span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">query</span><span class="p">}</span> <span class="p">{</span>
  1559. <span class="k">@content</span><span class="o">;</span>
  1560. <span class="p">}</span>
  1561. <span class="p">}</span> <span class="k">@else</span> <span class="p">{</span>
  1562. <span class="k">@error</span> <span class="s1">'</span><span class="s2">No value found for `</span><span class="si">#{</span><span class="nv">$breakpoint</span><span class="si">}</span><span class="s2">`. '</span>
  1563. <span class="o">+</span> <span class="s1">'</span><span class="s2">Please make sure it is defined in `$breakpoints` map.'</span><span class="o">;</span>
  1564. <span class="p">}</span>
  1565. <span class="p">}</span></code></pre></div>
  1566. </div>
  1567. <div class="code-block__wrapper" data-syntax="sass">
  1568. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Responsive manager.</span>
  1569. <span class="c1">/// @access public</span>
  1570. <span class="c1">/// @param {String} $breakpoint - Breakpoint</span>
  1571. <span class="c1">/// @requires $breakpoints</span>
  1572. <span class="nf">=respond-to</span><span class="p">(</span><span class="nv">$breakpoint</span><span class="p">)</span>
  1573. <span class="na">$raw-query</span><span class="o">:</span> <span class="nf">map-get</span><span class="p">(</span><span class="nv">$breakpoints</span><span class="o">,</span> <span class="nv">$breakpoint</span><span class="p">)</span>
  1574. <span class="k">@if</span> <span class="nv">$raw-query</span>
  1575. <span class="nv">$query</span><span class="o">:</span> <span class="nf">if</span><span class="p">(</span><span class="nf">type-of</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'</span><span class="s2">string'</span><span class="o">,</span> <span class="nf">unquote</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">)</span><span class="o">,</span> <span class="nf">inspect</span><span class="p">(</span><span class="nv">$raw-query</span><span class="p">))</span>
  1576. <span class="k">@media</span> <span class="nn">#</span><span class="err">{$</span><span class="nt">query</span><span class="err">}</span>
  1577. <span class="k">@content</span>
  1578. <span class="k">@else</span>
  1579. <span class="k">@error</span> <span class="s1">'</span><span class="s2">No value found for `</span><span class="si">#{</span><span class="nv">$breakpoint</span><span class="si">}</span><span class="s2">`. '</span>
  1580. <span class="o">+</span> <span class="s1">'</span><span class="s2">Please make sure it is defined in `$breakpoints` map.'</span></code></pre></div>
  1581. </div>
  1582. </div>
  1583. <div class="note">
  1584. <p>Obviously, this is a fairly simplistic breakpoint manager. If you need a slightly more permissive one, may I recommend you do not reinvent the wheel and use something that has been proven effective such as <a href="https://github.com/sass-mq/sass-mq">Sass-MQ</a>, <a href="http://breakpoint-sass.com/">Breakpoint</a> or <a href="https://github.com/eduardoboucas/include-media">include-media</a>.</p>
  1585. </div>
  1586. <h6 id="further-reading-21">Further reading</h6>
  1587. <p>Not so long ago, there was quite a hot debate about where media queries should be written: do they belong within selectors (as Sass allows it) or strictly dissociated from them? I have to say I am a fervent defender of the <em>media-queries-within-selectors</em> system, as I think it plays well with the ideas of <em>components</em>.</p>
  1588. <div class="code-block">
  1589. <div class="code-block__wrapper" data-syntax="scss">
  1590. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  1591. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  1592. <span class="k">@include</span><span class="nd"> respond-to</span><span class="p">(</span><span class="s1">'</span><span class="s2">medium'</span><span class="p">)</span> <span class="p">{</span>
  1593. <span class="na">color</span><span class="o">:</span> <span class="nb">blue</span><span class="p">;</span>
  1594. <span class="p">}</span>
  1595. <span class="p">}</span></code></pre></div>
  1596. </div>
  1597. <div class="code-block__wrapper" data-syntax="sass">
  1598. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  1599. <span class="na">color</span><span class="o">:</span> <span class="nb">red</span>
  1600. <span class="nd">+respond-to</span><span class="p">(</span><span class="s1">'</span><span class="s2">medium'</span><span class="p">)</span>
  1601. <span class="na">color</span><span class="o">:</span> <span class="nb">blue</span></code></pre></div>
  1602. </div>
  1603. </div>
  1604. <p>Leading to the following CSS output:</p>
  1605. <div>
  1606. <div class="highlight"><pre><code class="language-css" data-lang="css"><span class="nc">.foo</span> <span class="p">{</span>
  1607. <span class="k">color</span><span class="o">:</span> <span class="nb">red</span><span class="p">;</span>
  1608. <span class="p">}</span>
  1609. <span class="k">@media</span> <span class="o">(</span><span class="nt">min-width</span><span class="o">:</span> <span class="nt">800px</span><span class="o">)</span> <span class="p">{</span>
  1610. <span class="nc">.foo</span> <span class="p">{</span>
  1611. <span class="k">color</span><span class="o">:</span> <span class="nb">blue</span><span class="p">;</span>
  1612. <span class="p">}</span>
  1613. <span class="p">}</span></code></pre></div>
  1614. </div>
  1615. <p>You might hear that this convention results in duplicated media queries in the CSS output. That is definitely true. Although, <a href="http://sasscast.tumblr.com/post/38673939456/sass-and-media-queries">tests have been made</a> and the final word is that it doesn’t matter once Gzip (or any equivalent) has done its thing:</p>
  1616. <blockquote>
  1617. <p>… we hashed out whether there were performance implications of combining vs scattering Media Queries and came to the conclusion that the difference, while ugly, is minimal at worst, essentially non-existent at best.<br/>
  1618. — <a href="https://twitter.com/snugug">Sam Richards</a>, regarding <a href="http://breakpoint-sass.com/">Breakpoint</a></p>
  1619. </blockquote>
  1620. <p>Now, if you really are concerned about duplicated media queries, you can still use a tool to merge them such as <a href="https://github.com/aaronjensen/sass-media_query_combiner">this gem</a> however I feel like I have to warn you against possible side-effects of moving CSS code around. You are not without knowing that source order is important.</p>
  1621. <h6 id="further-reading-22">Further reading</h6>
  1622. <h1 id="variables">Variables</h1>
  1623. <p>Variables are the essence of any programming language. They allow us to reuse values without having to copy them over and over again. Most importantly, they make updating a value very easy. No more find and replace or manual crawling.</p>
  1624. <p>However CSS is nothing but a huge basket containing all our eggs. Unlike many languages, there are no real scopes in CSS. Because of this, we have to pay real attention when adding variables at the risk of witnessing conflicts.</p>
  1625. <p>My advice would be to only create variables when it makes sense to do so. Do not initiate new variables for the heck of it, it won’t help. A new variable should be created only when all of the following criteria are met:</p>
  1626. <ul>
  1627. <li>the value is repeated at least twice;</li>
  1628. <li>the value is likely to be updated at least once;</li>
  1629. <li>all occurrences of the value are tied to the variable (i.e. not by coincidence).</li>
  1630. </ul>
  1631. <p>Basically, there is no point declaring a variable that will never be updated or that is only being used at a single place.</p>
  1632. <h2 id="scoping">Scoping</h2>
  1633. <p>Variable scoping in Sass has changed over the years. Until fairly recently, variable declarations within rulesets and other scopes were local by default. However when there was already a global variable with the same name, the local assignment would change the global variable. Since version 3.4, Sass now properly tackles the concept of scopes and create a new local variable instead.</p>
  1634. <p>The docs talk about <em>global variable shadowing</em>. When declaring a variable that already exists on the global scope in an inner scope (selector, function, mixin…), the local variable is said to be <em>shadowing</em> the global one. Basically, it overrides it just for the local scope.</p>
  1635. <p>The following code snippet explains the <em>variable shadowing</em> concept.</p>
  1636. <div class="code-block">
  1637. <div class="code-block__wrapper" data-syntax="scss">
  1638. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Initialize a global variable at root level.</span>
  1639. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">initial value'</span><span class="p">;</span>
  1640. <span class="c1">// Create a mixin that overrides that global variable.</span>
  1641. <span class="k">@mixin</span><span class="nf"> global-variable-overriding</span> <span class="p">{</span>
  1642. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">mixin value'</span> <span class="nv">!global</span><span class="p">;</span>
  1643. <span class="p">}</span>
  1644. <span class="na">.local-scope</span><span class="o">::</span><span class="n">before</span> <span class="p">{</span>
  1645. <span class="c1">// Create a local variable that shadows the global one.</span>
  1646. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">local value'</span><span class="p">;</span>
  1647. <span class="c1">// Include the mixin: it overrides the global variable.</span>
  1648. <span class="k">@include</span><span class="nd"> global-variable-overriding</span><span class="p">;</span>
  1649. <span class="c1">// Print the variable’s value.</span>
  1650. <span class="c1">// It is the **local** one, since it shadows the global one.</span>
  1651. <span class="na">content</span><span class="o">:</span> <span class="nv">$variable</span><span class="p">;</span>
  1652. <span class="p">}</span>
  1653. <span class="c1">// Print the variable in another selector that does no shadowing.</span>
  1654. <span class="c1">// It is the **global** one, as expected.</span>
  1655. <span class="na">.other-local-scope</span><span class="o">::</span><span class="n">before</span> <span class="p">{</span>
  1656. <span class="na">content</span><span class="o">:</span> <span class="nv">$variable</span><span class="p">;</span>
  1657. <span class="p">}</span></code></pre></div>
  1658. </div>
  1659. <div class="code-block__wrapper" data-syntax="sass">
  1660. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Initialize a global variable at root level.</span>
  1661. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">initial value'</span>
  1662. <span class="c1">// Create a mixin that overrides that global variable.</span>
  1663. <span class="k">@mixin</span><span class="nf"> global-variable-overriding</span>
  1664. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">mixin value'</span> <span class="nv">!global</span>
  1665. <span class="na">.local-scope</span><span class="o">::</span><span class="n">before</span>
  1666. <span class="c1">// Create a local variable that shadows the global one.</span>
  1667. <span class="nv">$variable</span><span class="o">:</span> <span class="s1">'</span><span class="s2">local value'</span>
  1668. <span class="c1">// Include the mixin: it overrides the global variable.</span>
  1669. <span class="nd">+global-variable-overriding</span>
  1670. <span class="c1">// Print the variable’s value.</span>
  1671. <span class="c1">// It is the **local** one, since it shadows the global one.</span>
  1672. <span class="na">content</span><span class="o">:</span> <span class="nv">$variable</span>
  1673. <span class="c1">// Print the variable in another selector that does no shadowing.</span>
  1674. <span class="c1">// It is the **global** one, as expected.</span>
  1675. <span class="na">.other-local-scope</span><span class="o">::</span><span class="n">before</span>
  1676. <span class="na">content</span><span class="o">:</span> <span class="nv">$variable</span></code></pre></div>
  1677. </div>
  1678. </div>
  1679. <h2 id="default-flag"><code>!default</code> flag</h2>
  1680. <p>When building a library, a framework, a grid system or any piece of Sass that is intended to be distributed and used by external developers, all configuration variables should be defined with the <code>!default</code> flag so they can be overwritten.</p>
  1681. <p>Thanks to this, a developer can define his own <code>$baseline</code> variable <em>before</em> importing your library without seeing his value redefined.</p>
  1682. <div class="code-block">
  1683. <div class="code-block__wrapper" data-syntax="scss">
  1684. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Developer’s own variable</span>
  1685. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span><span class="p">;</span>
  1686. <span class="c1">// Your library declaring `$baseline`</span>
  1687. <span class="k">@import</span> <span class="s1">'</span><span class="s2">your-library'</span><span class="p">;</span>
  1688. <span class="c1">// $baseline == 2em;</span></code></pre></div>
  1689. </div>
  1690. <div class="code-block__wrapper" data-syntax="sass">
  1691. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Developer’s own variable</span>
  1692. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span>
  1693. <span class="c1">// Your library declaring `$baseline`</span>
  1694. <span class="k">@import</span> <span class="s">your-library</span>
  1695. <span class="c1">// $baseline == 2em</span></code></pre></div>
  1696. </div>
  1697. </div>
  1698. <h2 id="global-flag"><code>!global</code> flag</h2>
  1699. <p>The <code>!global</code> flag should only be used when overriding a global variable from a local scope. When defining a variable at root level, the <code>!global</code> flag should be omitted.</p>
  1700. <div class="code-block">
  1701. <div class="code-block__wrapper" data-syntax="scss">
  1702. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  1703. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span><span class="p">;</span>
  1704. <span class="c1">// Nope</span>
  1705. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span> <span class="nv">!global</span><span class="p">;</span></code></pre></div>
  1706. </div>
  1707. <div class="code-block__wrapper" data-syntax="sass">
  1708. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  1709. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span>
  1710. <span class="c1">// Nope</span>
  1711. <span class="nv">$baseline</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span> <span class="nv">!global</span></code></pre></div>
  1712. </div>
  1713. </div>
  1714. <h2 id="multiple-variables-or-maps">Multiple variables or maps</h2>
  1715. <p>There are advantages of using maps rather than multiple distinct variables. The main one is the ability to loop over a map, which is not possible with distinct variables.</p>
  1716. <p>Another pro of using a map is the ability to create a little getter function to provide a friendlier API. For instance, consider the following Sass code:</p>
  1717. <div class="code-block">
  1718. <div class="code-block__wrapper" data-syntax="scss">
  1719. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Z-indexes map, gathering all Z layers of the application</span>
  1720. <span class="c1">/// @access private</span>
  1721. <span class="c1">/// @type Map</span>
  1722. <span class="c1">/// @prop {String} key - Layer's name</span>
  1723. <span class="c1">/// @prop {Number} value - Z value mapped to the key</span>
  1724. <span class="nv">$z-indexes</span><span class="o">:</span> <span class="p">(</span>
  1725. <span class="s1">'</span><span class="s2">modal'</span><span class="o">:</span> <span class="mi">5000</span><span class="o">,</span>
  1726. <span class="s1">'</span><span class="s2">dropdown'</span><span class="o">:</span> <span class="mi">4000</span><span class="o">,</span>
  1727. <span class="s1">'</span><span class="s2">default'</span><span class="o">:</span> <span class="mi">1</span><span class="o">,</span>
  1728. <span class="s1">'</span><span class="s2">below'</span><span class="o">:</span> <span class="mi">-1</span><span class="o">,</span>
  1729. <span class="p">);</span>
  1730. <span class="c1">/// Get a z-index value from a layer name</span>
  1731. <span class="c1">/// @access public</span>
  1732. <span class="c1">/// @param {String} $layer - Layer’s name</span>
  1733. <span class="c1">/// @return {Number}</span>
  1734. <span class="c1">/// @require $z-indexes</span>
  1735. <span class="k">@function</span> <span class="nt">z</span><span class="o">(</span><span class="err">$</span><span class="nt">layer</span><span class="o">)</span> <span class="p">{</span>
  1736. <span class="k">@return</span> <span class="nt">map-get</span><span class="o">(</span><span class="err">$</span><span class="nt">z-indexes</span><span class="o">,</span> <span class="err">$</span><span class="nt">layer</span><span class="o">);</span>
  1737. <span class="p">}</span></code></pre></div>
  1738. </div>
  1739. <div class="code-block__wrapper" data-syntax="sass">
  1740. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Z-indexes map, gathering all Z layers of the application</span>
  1741. <span class="c1">/// @access private</span>
  1742. <span class="c1">/// @type Map</span>
  1743. <span class="c1">/// @prop {String} key - Layer’s name</span>
  1744. <span class="c1">/// @prop {Number} value - Z value mapped to the key</span>
  1745. <span class="na">$z-indexes</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">modal'</span><span class="o">:</span> <span class="mi">5000</span><span class="o">,</span> <span class="s1">'</span><span class="s2">dropdown'</span><span class="o">:</span> <span class="mi">4000</span><span class="o">,</span> <span class="s1">'</span><span class="s2">default'</span><span class="o">:</span> <span class="mi">1</span><span class="o">,</span> <span class="s1">'</span><span class="s2">below'</span><span class="o">:</span> <span class="mi">-1</span><span class="o">,</span><span class="p">)</span>
  1746. <span class="c1">/// Get a z-index value from a layer name</span>
  1747. <span class="c1">/// @access public</span>
  1748. <span class="c1">/// @param {String} $layer - Layer's name</span>
  1749. <span class="c1">/// @return {Number}</span>
  1750. <span class="c1">/// @require $z-indexes</span>
  1751. <span class="k">@function</span> <span class="nt">z</span><span class="o">(</span><span class="err">$</span><span class="nt">layer</span><span class="o">)</span>
  1752. <span class="k">@return</span> <span class="nt">map-get</span><span class="o">(</span><span class="err">$</span><span class="nt">z-indexes</span><span class="o">,</span> <span class="err">$</span><span class="nt">layer</span><span class="o">)</span></code></pre></div>
  1753. </div>
  1754. </div>
  1755. <h1 id="extend">Extend</h1>
  1756. <p>The <code>@extend</code> directive has to be one of the features that made Sass so popular a couple of years ago. As a reminder, it makes it possible to tell Sass to style an element A exactly as though it also matched selector B. Needless to say this can end up being a valuable ally when writing modular CSS.</p>
  1757. <p>However I feel like I must warn you against this feature. As clever as it is, <code>@extend</code> still is a tricky concept that might do more harm than good, especially when poorly used. The thing is, when extending a selector, you have little to no way to answer these questions without having an in-depth knowledge of the whole codebase:</p>
  1758. <ul>
  1759. <li>where is my current selector going to be appended?</li>
  1760. <li>am I likely to be causing undesired side-effects?</li>
  1761. <li>how large is the CSS generated by this single extend?</li>
  1762. </ul>
  1763. <p>For all you know, the result could range from doing nothing to causing disastrous side-effects. Because of this, my first advice would be to avoid the <code>@extend</code> directive altogether. It might sound brutal, but at the end of the day it can save you some headaches and troubles.</p>
  1764. <p>That being said, you know the saying:</p>
  1765. <blockquote>
  1766. <p>Never say never.<br/>
  1767. — Apparently, <a href="https://github.com/HugoGiraudel/sass-guidelines/issues/31#issuecomment-69112419">not Beyonce</a>.</p>
  1768. </blockquote>
  1769. <p>There are scenarios where extending selectors might be helpful and worthwhile. Yet, always keep in mind those rules so you don’t get yourself into trouble:</p>
  1770. <ul>
  1771. <li>Use extend from within a module, not across different modules.</li>
  1772. <li>Use extend on placeholders exclusively, not on actual selectors.</li>
  1773. <li>Make sure the placeholder you extend is present as little as possible in the stylesheet.</li>
  1774. </ul>
  1775. <p>If you are going to use extend, let me also remind you that it does not play well with <code>@media</code> blocks. As you may know, Sass is unable to extend an outer selector from within a media query. When doing so, the compiler simply crashes, telling you that you cannot do such a thing. Not great. Especially since media queries are almost all we do know.</p>
  1776. <div class="code-block">
  1777. <div class="code-block__wrapper" data-syntax="scss">
  1778. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  1779. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">foo'</span><span class="p">;</span>
  1780. <span class="p">}</span>
  1781. <span class="k">@media</span> <span class="nt">print</span> <span class="p">{</span>
  1782. <span class="nc">.bar</span> <span class="p">{</span>
  1783. <span class="c1">// This doesn't work. Worse: it crashes.</span>
  1784. <span class="k">@extend</span> <span class="nc">.foo</span><span class="o">;</span>
  1785. <span class="p">}</span>
  1786. <span class="p">}</span></code></pre></div>
  1787. </div>
  1788. <div class="code-block__wrapper" data-syntax="sass">
  1789. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  1790. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">foo'</span>
  1791. <span class="k">@media</span> <span class="nt">print</span>
  1792. <span class="nc">.bar</span>
  1793. <span class="c1">// This doesn't work. Worse: it crashes.</span>
  1794. <span class="k">@extend</span> <span class="nc">.foo</span></code></pre></div>
  1795. </div>
  1796. </div>
  1797. <blockquote>
  1798. <p>You may not @extend an outer selector from within @media.<br/>
  1799. You may only @extend selectors within the same directive.</p>
  1800. </blockquote>
  1801. <div class="note">
  1802. <p>It is often said that <code>@extend</code> helps with the file size since it combines selectors rather than duplicated properties. That is true, however the difference is negligible once <a href="http://en.wikipedia.org/wiki/Gzip">Gzip</a> has done its compression.</p>
  1803. <p>That being said, if you cannot use Gzip (or any equivalent) then switching to a <code>@extend</code> approach might not be that bad as long as you know what you are doing.</p>
  1804. </div>
  1805. <p>To sum up, I would <strong>advise against using the <code>@extend</code> directive</strong>, unless under some specific circumstances, but I would not go as far as to forbid it.</p>
  1806. <h6 id="further-reading-23">Further reading</h6>
  1807. <h1 id="mixins">Mixins</h1>
  1808. <p>Mixins are one of the most used features from the whole Sass language. They are the key to reusability and DRY components. And for good reason: mixins allow authors to define styles that can be reused throughout the stylesheet without needing to resort to non-semantic classes such as <code>.float-left</code>.</p>
  1809. <p>They can contain full CSS rules and pretty much everything that is allowed anywhere in a Sass document. They can even take arguments, just like functions. Needless to say, the possibilities are endless.</p>
  1810. <p>But I feel I must warn you against abusing the power of mixins. Again, the keyword here is <em>simplicity</em>. It might be tempting to build extremely powerful mixins with massive amounts of logic. It’s called over-engineering and most developers suffer from it. Don’t over think your code, and above all keep it simple. If a mixin ends up being longer than 20 lines or so, then it should be either split into smaller chunks or completely revised.</p>
  1811. <h2 id="basics">Basics</h2>
  1812. <p>That being said, mixins are extremely useful and you should be using some. The rule of thumb is that if you happen to spot a group of CSS properties that always appear together for a reason (i.e. not a coincidence), you can put them in a mixin instead. The <a href="http://nicolasgallagher.com/micro-clearfix-hack/">micro-clearfix hack from Nicolas Gallagher</a> deserves to be put in a (argumentless) mixin for instance.</p>
  1813. <div class="code-block">
  1814. <div class="code-block__wrapper" data-syntax="scss">
  1815. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Helper to clear inner floats</span>
  1816. <span class="c1">/// @author Nicolas Gallagher</span>
  1817. <span class="c1">/// @link http://nicolasgallagher.com/micro-clearfix-hack/ Micro Clearfix</span>
  1818. <span class="k">@mixin</span><span class="nf"> clearfix</span> <span class="p">{</span>
  1819. <span class="na">&amp;</span><span class="o">::</span><span class="n">after</span> <span class="p">{</span>
  1820. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">'</span><span class="p">;</span>
  1821. <span class="na">display</span><span class="o">:</span> <span class="n">table</span><span class="p">;</span>
  1822. <span class="na">clear</span><span class="o">:</span> <span class="no">both</span><span class="p">;</span>
  1823. <span class="p">}</span>
  1824. <span class="p">}</span></code></pre></div>
  1825. </div>
  1826. <div class="code-block__wrapper" data-syntax="sass">
  1827. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Helper to clear inner floats</span>
  1828. <span class="c1">/// @author Nicolas Gallagher</span>
  1829. <span class="c1">/// @link http://nicolasgallagher.com/micro-clearfix-hack/ Micro Clearfix</span>
  1830. <span class="k">@mixin</span><span class="nf"> clearfix</span>
  1831. <span class="na">&amp;</span><span class="o">::</span><span class="n">after</span>
  1832. <span class="na">content</span><span class="o">:</span> <span class="s1">'</span><span class="s2">'</span>
  1833. <span class="na">display</span><span class="o">:</span> <span class="n">table</span>
  1834. <span class="na">clear</span><span class="o">:</span> <span class="no">both</span></code></pre></div>
  1835. </div>
  1836. </div>
  1837. <p>Another valid example would be a mixin to size an element, defining both <code>width</code> and <code>height</code> at the same time. Not only would it make the code lighter to type, but also easier to read.</p>
  1838. <div class="code-block">
  1839. <div class="code-block__wrapper" data-syntax="scss">
  1840. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Helper to size an element</span>
  1841. <span class="c1">/// @author Hugo Giraudel</span>
  1842. <span class="c1">/// @param {Length} $width</span>
  1843. <span class="c1">/// @param {Length} $height</span>
  1844. <span class="k">@mixin</span><span class="nf"> size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span> <span class="p">{</span>
  1845. <span class="na">width</span><span class="o">:</span> <span class="nv">$width</span><span class="p">;</span>
  1846. <span class="na">height</span><span class="o">:</span> <span class="nv">$height</span><span class="p">;</span>
  1847. <span class="p">}</span></code></pre></div>
  1848. </div>
  1849. <div class="code-block__wrapper" data-syntax="sass">
  1850. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Helper to size an element</span>
  1851. <span class="c1">/// @author Hugo Giraudel</span>
  1852. <span class="c1">/// @param {Length} $width</span>
  1853. <span class="c1">/// @param {Length} $height</span>
  1854. <span class="nf">=size</span><span class="p">(</span><span class="nv">$width</span><span class="o">,</span> <span class="nv">$height</span><span class="o">:</span> <span class="nv">$width</span><span class="p">)</span>
  1855. <span class="na">width</span><span class="o">:</span> <span class="nv">$width</span>
  1856. <span class="na">height</span><span class="o">:</span> <span class="nv">$height</span></code></pre></div>
  1857. </div>
  1858. </div>
  1859. <h6 id="further-reading-24">Further reading</h6>
  1860. <h2 id="arguments-list">Arguments list</h2>
  1861. <p>When dealing with an unknown number of arguments in a mixin, always use an <code>arglist</code> rather than a list. Think of <code>arglist</code> as the 8th hidden undocumented data type from Sass that is implicitly used when passing an arbitrary number of arguments to a mixin or a function whose signature contains <code>...</code>.</p>
  1862. <div class="code-block">
  1863. <div class="code-block__wrapper" data-syntax="scss">
  1864. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@mixin</span><span class="nf"> shadows</span><span class="p">(</span><span class="nv">$shadows</span><span class="o">...</span><span class="p">)</span> <span class="p">{</span>
  1865. <span class="c1">// type-of($shadows) == 'arglist'</span>
  1866. <span class="c1">// ...</span>
  1867. <span class="p">}</span></code></pre></div>
  1868. </div>
  1869. <div class="code-block__wrapper" data-syntax="sass">
  1870. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nf">=shadows</span><span class="p">(</span><span class="nv">$shadows</span><span class="o">...</span><span class="p">)</span>
  1871. <span class="c1">// type-of($shadows) == 'arglist'</span>
  1872. <span class="c1">// ...</span></code></pre></div>
  1873. </div>
  1874. </div>
  1875. <p>Now, when building a mixin that accepts a handful of arguments (understand 3 or more), think twice before merging them out as a list or a map thinking it will be easier than passing them all one by one.</p>
  1876. <p>Sass is actually pretty clever with mixins and function declarations, so much so that you can actually pass a list or a map as an arglist to a function/mixin so that it gets parsed as a series of arguments.</p>
  1877. <div class="code-block">
  1878. <div class="code-block__wrapper" data-syntax="scss">
  1879. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@mixin</span><span class="nf"> dummy</span><span class="p">(</span><span class="nv">$a</span><span class="o">,</span> <span class="nv">$b</span><span class="o">,</span> <span class="nv">$c</span><span class="p">)</span> <span class="p">{</span>
  1880. <span class="c1">// ...</span>
  1881. <span class="p">}</span>
  1882. <span class="c1">// Yep</span>
  1883. <span class="k">@include</span><span class="nd"> dummy</span><span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">);</span>
  1884. <span class="c1">// Yep but nope</span>
  1885. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">);</span>
  1886. <span class="nv">$value</span><span class="o">:</span> <span class="nf">dummy</span><span class="p">(</span><span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">,</span> <span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">,</span> <span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">3</span><span class="p">));</span>
  1887. <span class="c1">// Yep</span>
  1888. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">);</span>
  1889. <span class="k">@include</span><span class="nd"> dummy</span><span class="p">(</span><span class="nv">$params</span><span class="o">...</span><span class="p">);</span>
  1890. <span class="c1">// Yep</span>
  1891. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span>
  1892. <span class="s1">'</span><span class="s2">c'</span><span class="o">:</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="o">,</span>
  1893. <span class="s1">'</span><span class="s2">a'</span><span class="o">:</span> <span class="n-Pseudo">true</span><span class="o">,</span>
  1894. <span class="s1">'</span><span class="s2">b'</span><span class="o">:</span> <span class="mi">42</span><span class="o">,</span>
  1895. <span class="p">);</span>
  1896. <span class="k">@include</span><span class="nd"> dummy</span><span class="p">(</span><span class="nv">$params</span><span class="o">...</span><span class="p">);</span></code></pre></div>
  1897. </div>
  1898. <div class="code-block__wrapper" data-syntax="sass">
  1899. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nf">=dummy</span><span class="p">(</span><span class="nv">$a</span><span class="o">,</span> <span class="nv">$b</span><span class="o">,</span> <span class="nv">$c</span><span class="p">)</span>
  1900. <span class="c1">// ...</span>
  1901. <span class="c1">// Yep</span>
  1902. <span class="nd">+dummy</span><span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">)</span>
  1903. <span class="c1">// Yep but nope</span>
  1904. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">)</span>
  1905. <span class="nv">$value</span><span class="o">:</span> <span class="nf">dummy</span><span class="p">(</span><span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">,</span> <span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">,</span> <span class="nf">nth</span><span class="p">(</span><span class="nv">$params</span><span class="o">,</span> <span class="mi">3</span><span class="p">))</span>
  1906. <span class="c1">// Yep</span>
  1907. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span><span class="n-Pseudo">true</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="p">)</span>
  1908. <span class="nd">+dummy</span><span class="p">(</span><span class="nv">$params</span><span class="o">...</span><span class="p">)</span>
  1909. <span class="c1">// Yep</span>
  1910. <span class="nv">$params</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">c'</span><span class="o">:</span> <span class="s1">'</span><span class="s2">kittens'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">a'</span><span class="o">:</span> <span class="n-Pseudo">true</span><span class="o">,</span> <span class="s1">'</span><span class="s2">b'</span><span class="o">:</span> <span class="mi">42</span><span class="o">,</span><span class="p">)</span>
  1911. <span class="nd">+dummy</span><span class="p">(</span><span class="nv">$params</span><span class="o">...</span><span class="p">)</span></code></pre></div>
  1912. </div>
  1913. </div>
  1914. <h6 id="further-reading-25">Further reading</h6>
  1915. <h2 id="mixins-and-vendor-prefixes">Mixins and vendor prefixes</h2>
  1916. <p>It might be tempting to define custom mixins to handle vendor prefixes for unsupported or partially supported CSS properties. But we do not want to do this. First, if you can use <a href="https://github.com/postcss/autoprefixer">Autoprefixer</a>, use Autoprefixer. It will remove Sass code from your project, will always be up-to-date and will necessarily do a much better job than you at prefixing stuff.</p>
  1917. <p>Unfortunately, Autoprefixer is not always an option. If you use either <a href="http://bourbon.io/">Bourbon</a> or <a href="http://compass-style.org/">Compass</a>, you may already know that they both provide a collection of mixins that handle vendor prefixes for you. Use those.</p>
  1918. <p>If you cannot use Autoprefixer and use neither Bourbon nor Compass, then and only then, you can have your own mixin for prefixing CSS properties. But. Please do not build a mixin per property, manually printing each vendor.</p>
  1919. <div class="code-block">
  1920. <div class="code-block__wrapper" data-syntax="scss">
  1921. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Nope</span>
  1922. <span class="k">@mixin</span><span class="nf"> transform</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span> <span class="p">{</span>
  1923. <span class="na">-webkit-transform</span><span class="o">:</span> <span class="nv">$value</span><span class="p">;</span>
  1924. <span class="na">-moz-transform</span><span class="o">:</span> <span class="nv">$value</span><span class="p">;</span>
  1925. <span class="na">transform</span><span class="o">:</span> <span class="nv">$value</span><span class="p">;</span>
  1926. <span class="p">}</span></code></pre></div>
  1927. </div>
  1928. <div class="code-block__wrapper" data-syntax="sass">
  1929. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Nope</span>
  1930. <span class="nf">=transform</span><span class="p">(</span><span class="nv">$value</span><span class="p">)</span>
  1931. <span class="na">-webkit-transform</span><span class="o">:</span> <span class="nv">$value</span>
  1932. <span class="na">-moz-transform</span><span class="o">:</span> <span class="nv">$value</span>
  1933. <span class="na">transform</span><span class="o">:</span> <span class="nv">$value</span></code></pre></div>
  1934. </div>
  1935. </div>
  1936. <p>Do it the clever way.</p>
  1937. <div class="code-block">
  1938. <div class="code-block__wrapper" data-syntax="scss">
  1939. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Mixin helper to output vendor prefixes</span>
  1940. <span class="c1">/// @access public</span>
  1941. <span class="c1">/// @author HugoGiraudel</span>
  1942. <span class="c1">/// @param {String} $property - Unprefixed CSS property</span>
  1943. <span class="c1">/// @param {*} $value - Raw CSS value</span>
  1944. <span class="c1">/// @param {List} $prefixes - List of prefixes to output</span>
  1945. <span class="k">@mixin</span><span class="nf"> prefix</span><span class="p">(</span><span class="nv">$property</span><span class="o">,</span> <span class="nv">$value</span><span class="o">,</span> <span class="nv">$prefixes</span><span class="o">:</span> <span class="p">())</span> <span class="p">{</span>
  1946. <span class="k">@each</span> <span class="err">$</span><span class="nt">prefix</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">prefixes</span> <span class="p">{</span>
  1947. <span class="nt">-</span><span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">prefix</span><span class="p">}</span><span class="nt">-</span><span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">property</span><span class="p">}</span><span class="nd">:</span> <span class="err">$</span><span class="nt">value</span><span class="o">;</span>
  1948. <span class="p">}</span>
  1949. <span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">property</span><span class="p">}</span><span class="nd">:</span> <span class="err">$</span><span class="nt">value</span><span class="o">;</span>
  1950. <span class="p">}</span></code></pre></div>
  1951. </div>
  1952. <div class="code-block__wrapper" data-syntax="sass">
  1953. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Mixin helper to output vendor prefixes</span>
  1954. <span class="c1">/// @access public</span>
  1955. <span class="c1">/// @author HugoGiraudel</span>
  1956. <span class="c1">/// @param {String} $property - Unprefixed CSS property</span>
  1957. <span class="c1">/// @param {*} $value - Raw CSS value</span>
  1958. <span class="c1">/// @param {List} $prefixes - List of prefixes to output</span>
  1959. <span class="nf">=prefix</span><span class="p">(</span><span class="nv">$property</span><span class="o">,</span> <span class="nv">$value</span><span class="o">,</span> <span class="nv">$prefixes</span><span class="o">:</span> <span class="p">())</span>
  1960. <span class="k">@each</span> <span class="err">$</span><span class="nt">prefix</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">prefixes</span>
  1961. <span class="na">-#{$prefix}-#{$property}</span><span class="o">:</span> <span class="nv">$value</span>
  1962. <span class="na">#{$property}</span><span class="o">:</span> <span class="nv">$value</span></code></pre></div>
  1963. </div>
  1964. </div>
  1965. <p>Then using this mixin should be very straightforward:</p>
  1966. <div class="code-block">
  1967. <div class="code-block__wrapper" data-syntax="scss">
  1968. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="nc">.foo</span> <span class="p">{</span>
  1969. <span class="k">@include</span><span class="nd"> prefix</span><span class="p">(</span><span class="n">transform</span><span class="o">,</span> <span class="nf">rotate</span><span class="p">(</span><span class="mi">90</span><span class="kt">deg</span><span class="p">)</span><span class="o">,</span> <span class="p">(</span><span class="s1">'</span><span class="s2">webkit'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">ms'</span><span class="p">));</span>
  1970. <span class="p">}</span></code></pre></div>
  1971. </div>
  1972. <div class="code-block__wrapper" data-syntax="sass">
  1973. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="nc">.foo</span>
  1974. <span class="nd">+prefix</span><span class="p">(</span><span class="n">transform</span><span class="o">,</span> <span class="nf">rotate</span><span class="p">(</span><span class="mi">90</span><span class="kt">deg</span><span class="p">)</span><span class="o">,</span> <span class="p">(</span><span class="s1">'</span><span class="s2">webkit'</span><span class="o">,</span> <span class="s1">'</span><span class="s2">ms'</span><span class="p">))</span></code></pre></div>
  1975. </div>
  1976. </div>
  1977. <p>Please keep in mind this is a poor solution. For instance, it cannot deal with complex polyfills such as those required for Flexbox. In that sense, using Autoprefixer would be a far better option.</p>
  1978. <h6 id="further-reading-26">Further reading</h6>
  1979. <h1 id="conditional-statements">Conditional statements</h1>
  1980. <p>You probably already know that Sass provides conditional statements via the <code>@if</code> and <code>@else</code> directives. Unless you have some medium to complex logic in your code, there is no need for conditional statements in your everyday stylesheets. Actually, they mainly exist for libraries and frameworks.</p>
  1981. <p>Anyway, if you ever find yourself in need of them, please respect the following guidelines:</p>
  1982. <ul>
  1983. <li>No parentheses unless they are necessary;</li>
  1984. <li>Always an empty new line before <code>@if</code>;</li>
  1985. <li>Always a line break after the opening brace (<code>{</code>);</li>
  1986. <li><code>@else</code> statements on the same line as previous closing brace (<code>}</code>).</li>
  1987. <li>Always an empty new line after the last closing brace (<code>}</code>) unless the next line is a closing brace (<code>}</code>).</li>
  1988. </ul>
  1989. <div class="code-block">
  1990. <div class="code-block__wrapper" data-syntax="scss">
  1991. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  1992. <span class="k">@if</span> <span class="nv">$support-legacy</span> <span class="p">{</span>
  1993. <span class="c1">// ...</span>
  1994. <span class="p">}</span> <span class="k">@else</span> <span class="p">{</span>
  1995. <span class="c1">// ...</span>
  1996. <span class="p">}</span>
  1997. <span class="c1">// Nope</span>
  1998. <span class="k">@if</span> <span class="p">(</span><span class="nv">$support-legacy</span> <span class="o">==</span> <span class="n-Pseudo">true</span><span class="p">)</span> <span class="p">{</span>
  1999. <span class="c1">// ...</span>
  2000. <span class="p">}</span>
  2001. <span class="k">@else</span> <span class="p">{</span>
  2002. <span class="c1">// ...</span>
  2003. <span class="p">}</span></code></pre></div>
  2004. </div>
  2005. <div class="code-block__wrapper" data-syntax="sass">
  2006. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  2007. <span class="k">@if</span> <span class="nv">$support-legacy</span>
  2008. <span class="c1">// ...</span>
  2009. <span class="k">@else</span>
  2010. <span class="c1">// ...</span>
  2011. <span class="c1">// Nope</span>
  2012. <span class="k">@if</span> <span class="p">(</span><span class="nv">$support-legacy</span> <span class="o">==</span> <span class="n-Pseudo">true</span><span class="p">)</span>
  2013. <span class="c1">// ...</span>
  2014. <span class="k">@else</span>
  2015. <span class="c1">// ...</span></code></pre></div>
  2016. </div>
  2017. </div>
  2018. <p>When testing for a falsy value, always use the <code>not</code> keyword rather than testing against <code>false</code> or <code>null</code>.</p>
  2019. <div class="code-block">
  2020. <div class="code-block__wrapper" data-syntax="scss">
  2021. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  2022. <span class="k">@if</span> <span class="ow">not</span> <span class="nf">index</span><span class="p">(</span><span class="nv">$list</span><span class="o">,</span> <span class="nv">$item</span><span class="p">)</span> <span class="p">{</span>
  2023. <span class="c1">// ...</span>
  2024. <span class="p">}</span>
  2025. <span class="c1">// Nope</span>
  2026. <span class="k">@if</span> <span class="nf">index</span><span class="p">(</span><span class="nv">$list</span><span class="o">,</span> <span class="nv">$item</span><span class="p">)</span> <span class="o">==</span> <span class="n">null</span> <span class="p">{</span>
  2027. <span class="c1">// ...</span>
  2028. <span class="p">}</span></code></pre></div>
  2029. </div>
  2030. <div class="code-block__wrapper" data-syntax="sass">
  2031. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  2032. <span class="k">@if</span> <span class="ow">not</span> <span class="nf">index</span><span class="p">(</span><span class="nv">$list</span><span class="o">,</span> <span class="nv">$item</span><span class="p">)</span>
  2033. <span class="c1">// ...</span>
  2034. <span class="c1">// Nope</span>
  2035. <span class="k">@if</span> <span class="nf">index</span><span class="p">(</span><span class="nv">$list</span><span class="o">,</span> <span class="nv">$item</span><span class="p">)</span> <span class="o">==</span> <span class="n">null</span>
  2036. <span class="c1">// ...</span></code></pre></div>
  2037. </div>
  2038. </div>
  2039. <p>Always put the variable part on the left side of the statement, and the (un)expected result on the right. Reversed conditional statements often are more difficult to read, especially to unexperienced developers.</p>
  2040. <div class="code-block">
  2041. <div class="code-block__wrapper" data-syntax="scss">
  2042. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  2043. <span class="k">@if</span> <span class="nv">$value</span> <span class="o">==</span> <span class="mi">42</span> <span class="p">{</span>
  2044. <span class="c1">// ...</span>
  2045. <span class="p">}</span>
  2046. <span class="c1">// Nope</span>
  2047. <span class="k">@if</span> <span class="mi">42</span> <span class="o">==</span> <span class="nv">$value</span> <span class="p">{</span>
  2048. <span class="c1">// ...</span>
  2049. <span class="p">}</span></code></pre></div>
  2050. </div>
  2051. <div class="code-block__wrapper" data-syntax="sass">
  2052. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  2053. <span class="k">@if</span> <span class="nv">$value</span> <span class="o">==</span> <span class="mi">42</span>
  2054. <span class="c1">// ...</span>
  2055. <span class="c1">// Nope</span>
  2056. <span class="k">@if</span> <span class="mi">42</span> <span class="o">==</span> <span class="nv">$value</span>
  2057. <span class="c1">// ...</span></code></pre></div>
  2058. </div>
  2059. </div>
  2060. <p>When using conditional statements within a function to return a different result based on some condition, always make sure the function still has a <code>@return</code> statement outside of any conditional block.</p>
  2061. <div class="code-block">
  2062. <div class="code-block__wrapper" data-syntax="scss">
  2063. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">// Yep</span>
  2064. <span class="k">@function</span> <span class="nt">dummy</span><span class="o">(</span><span class="err">$</span><span class="nt">condition</span><span class="o">)</span> <span class="p">{</span>
  2065. <span class="k">@if</span> <span class="nv">$condition</span> <span class="p">{</span>
  2066. <span class="k">@return</span> <span class="nt">true</span><span class="o">;</span>
  2067. <span class="p">}</span>
  2068. <span class="k">@return</span> <span class="nt">false</span><span class="o">;</span>
  2069. <span class="p">}</span>
  2070. <span class="c1">// Nope</span>
  2071. <span class="k">@function</span> <span class="nt">dummy</span><span class="o">(</span><span class="err">$</span><span class="nt">condition</span><span class="o">)</span> <span class="p">{</span>
  2072. <span class="k">@if</span> <span class="nv">$condition</span> <span class="p">{</span>
  2073. <span class="k">@return</span> <span class="nt">true</span><span class="o">;</span>
  2074. <span class="p">}</span> <span class="k">@else</span> <span class="p">{</span>
  2075. <span class="k">@return</span> <span class="nt">false</span><span class="o">;</span>
  2076. <span class="p">}</span>
  2077. <span class="p">}</span></code></pre></div>
  2078. </div>
  2079. <div class="code-block__wrapper" data-syntax="sass">
  2080. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">// Yep</span>
  2081. <span class="k">@function</span> <span class="nt">dummy</span><span class="o">(</span><span class="err">$</span><span class="nt">condition</span><span class="o">)</span>
  2082. <span class="k">@if</span> <span class="nv">$condition</span>
  2083. <span class="k">@return</span> <span class="nt">true</span>
  2084. <span class="k">@return</span> <span class="nt">false</span><span class="o">;</span>
  2085. <span class="c1">// Nope</span>
  2086. <span class="k">@function</span> <span class="nt">dummy</span><span class="o">(</span><span class="err">$</span><span class="nt">condition</span><span class="o">)</span>
  2087. <span class="k">@if</span> <span class="nv">$condition</span>
  2088. <span class="k">@return</span> <span class="nt">true</span>
  2089. <span class="k">@else</span>
  2090. <span class="k">@return</span> <span class="nt">false</span></code></pre></div>
  2091. </div>
  2092. </div>
  2093. <h1 id="loops">Loops</h1>
  2094. <p>Because Sass provides complex data structures such as <a href="#lists">lists</a> and <a href="#maps">maps</a>, it is no surprise that it also gives a way for authors to iterate over those entities.</p>
  2095. <p>However, the presence of loops usually implies moderately complex logic that probably does not belong to Sass. Before using a loop, make sure it makes sense and that it actually solves an issue.</p>
  2096. <h2 id="each">Each</h2>
  2097. <p>The <code>@each</code> loop is definitely the most-used out of the three loops provided by Sass. It provides a clean API to iterate over a list or a map.</p>
  2098. <div class="code-block">
  2099. <div class="code-block__wrapper" data-syntax="scss">
  2100. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@each</span> <span class="err">$</span><span class="nt">theme</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">themes</span> <span class="p">{</span>
  2101. <span class="nc">.section-</span><span class="si">#{</span><span class="nv">$theme</span><span class="si">}</span> <span class="p">{</span>
  2102. <span class="na">background-color</span><span class="o">:</span> <span class="nf">map-get</span><span class="p">(</span><span class="nv">$colors</span><span class="o">,</span> <span class="nv">$theme</span><span class="p">);</span>
  2103. <span class="p">}</span>
  2104. <span class="p">}</span></code></pre></div>
  2105. </div>
  2106. <div class="code-block__wrapper" data-syntax="sass">
  2107. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@each</span> <span class="err">$</span><span class="nt">theme</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">themes</span>
  2108. <span class="nc">.section-</span><span class="si">#{</span><span class="nv">$theme</span><span class="si">}</span>
  2109. <span class="na">background-color</span><span class="o">:</span> <span class="nf">map-get</span><span class="p">(</span><span class="nv">$colors</span><span class="o">,</span> <span class="nv">$theme</span><span class="p">)</span></code></pre></div>
  2110. </div>
  2111. </div>
  2112. <p>When iterating on a map, always use <code>$key</code> and <code>$value</code> as variable names to enforce consistency.</p>
  2113. <div class="code-block">
  2114. <div class="code-block__wrapper" data-syntax="scss">
  2115. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span> <span class="p">{</span>
  2116. <span class="nc">.section-</span><span class="si">#{</span><span class="nv">$key</span><span class="si">}</span> <span class="p">{</span>
  2117. <span class="na">background-color</span><span class="o">:</span> <span class="nv">$value</span><span class="p">;</span>
  2118. <span class="p">}</span>
  2119. <span class="p">}</span></code></pre></div>
  2120. </div>
  2121. <div class="code-block__wrapper" data-syntax="sass">
  2122. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@each</span> <span class="err">$</span><span class="nt">key</span><span class="o">,</span> <span class="err">$</span><span class="nt">value</span> <span class="nt">in</span> <span class="err">$</span><span class="nt">map</span>
  2123. <span class="nc">.section-</span><span class="si">#{</span><span class="nv">$key</span><span class="si">}</span>
  2124. <span class="na">background-color</span><span class="o">:</span> <span class="nv">$value</span></code></pre></div>
  2125. </div>
  2126. </div>
  2127. <p>Also be sure to respect those guidelines to preserve readability:</p>
  2128. <ul>
  2129. <li>Always an empty new line before <code>@each</code>;</li>
  2130. <li>Always an empty new line after the closing brace (<code>}</code>) unless the next line is a closing brace (<code>}</code>).</li>
  2131. </ul>
  2132. <h2 id="for">For</h2>
  2133. <p>The <code>@for</code> loop might be useful when combined with CSS’ <code>:nth-*</code> pseudo-classes. Except for these scenarios, prefer an <code>@each</code> loop if you <em>have to</em> iterate over something.</p>
  2134. <div class="code-block">
  2135. <div class="code-block__wrapper" data-syntax="scss">
  2136. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@for</span> <span class="nv">$i</span> <span class="ow">from</span> <span class="mi">1</span> <span class="ow">through</span> <span class="mi">10</span> <span class="p">{</span>
  2137. <span class="nc">.foo</span><span class="nd">:nth-of-type</span><span class="o">(</span><span class="nn">#</span><span class="p">{</span><span class="err">$</span><span class="nt">i</span><span class="p">}</span><span class="o">)</span> <span class="p">{</span>
  2138. <span class="na">border-color</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span><span class="nv">$i</span> <span class="o">*</span> <span class="mi">36</span><span class="o">,</span> <span class="mi">50</span><span class="kt">%</span><span class="o">,</span> <span class="mi">50</span><span class="kt">%</span><span class="p">);</span>
  2139. <span class="p">}</span>
  2140. <span class="p">}</span></code></pre></div>
  2141. </div>
  2142. <div class="code-block__wrapper" data-syntax="sass">
  2143. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@for</span> <span class="nv">$i</span> <span class="ow">from</span> <span class="mi">1</span> <span class="ow">through</span> <span class="mi">10</span>
  2144. <span class="nc">.foo</span><span class="nd">:nth-of-type</span><span class="o">(</span><span class="nn">#</span><span class="err">{$</span><span class="nt">i</span><span class="err">}</span><span class="o">)</span>
  2145. <span class="na">border-color</span><span class="o">:</span> <span class="nf">hsl</span><span class="p">(</span><span class="nv">$i</span> <span class="o">*</span> <span class="mi">36</span><span class="o">,</span> <span class="mi">50</span><span class="kt">%</span><span class="o">,</span> <span class="mi">50</span><span class="kt">%</span><span class="p">)</span></code></pre></div>
  2146. </div>
  2147. </div>
  2148. <p>Always use <code>$i</code> as a variable name to stick to the usual convention and unless you have a really good reason to, never use the <code>to</code> keyword: always use <code>through</code>. Many developers do not even know Sass offers this variation; using it might lead to confusion.</p>
  2149. <p>Also be sure to respect those guidelines to preserve readability:</p>
  2150. <ul>
  2151. <li>Always an empty new line before <code>@for</code>;</li>
  2152. <li>Always an empty new line after the closing brace (<code>}</code>) unless the next line is a closing brace (<code>}</code>).</li>
  2153. </ul>
  2154. <h2 id="while">While</h2>
  2155. <p>The <code>@while</code> loop has absolutely no use case in a real Sass project, especially since there is no way to break a loop from the inside. <strong>Do not use it</strong>.</p>
  2156. <h1 id="warnings-and-errors">Warnings and Errors</h1>
  2157. <p>If there is a feature that is often overlooked by Sass developers, it is the ability to dynamically output warnings and errors. Indeed, Sass comes with three custom directives to print content in the standard output system (CLI, compiling app…):</p>
  2158. <p>Let’s put <code>@debug</code> aside since it is clearly intended to debug SassScript, which is not our point here. We are then left with <code>@warn</code> and <code>@error</code> which are noticeably identical except that one stops the compiler while the other does not. I’ll let you guess which does what.</p>
  2159. <p>Now, there is a lot of room in a Sass project for warnings and errors. Basically any mixin or function expecting a specific type or argument could throw an error if something went wrong, or display a warning when doing an assumption.</p>
  2160. <h6 id="further-reading-27">Further reading</h6>
  2161. <h2 id="warnings">Warnings</h2>
  2162. <p>Take this function from <a href="https://github.com/sass-mq/sass-mq">Sass-MQ</a> attempting to convert a <code>px</code> value to <code>em</code>, for instance:</p>
  2163. <div class="code-block">
  2164. <div class="code-block__wrapper" data-syntax="scss">
  2165. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="k">@function</span> <span class="nt">mq-px2em</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span><span class="o">,</span> <span class="err">$</span><span class="nt">base-font-size</span><span class="nd">:</span> <span class="err">$</span><span class="nt">mq-base-font-size</span><span class="o">)</span> <span class="p">{</span>
  2166. <span class="k">@if</span> <span class="nf">unitless</span><span class="p">(</span><span class="nv">$px</span><span class="p">)</span> <span class="p">{</span>
  2167. <span class="k">@warn</span> <span class="s1">'</span><span class="s2">Assuming </span><span class="si">#{</span><span class="nv">$px</span><span class="si">}</span><span class="s2"> to be in pixels, attempting to convert it into pixels.'</span><span class="p">;</span>
  2168. <span class="k">@return</span> <span class="nt">mq-px2em</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span> <span class="o">+</span> <span class="nt">0px</span><span class="o">);</span>
  2169. <span class="p">}</span> <span class="k">@else</span> <span class="nt">if</span> <span class="nt">unit</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span><span class="o">)</span> <span class="o">==</span> <span class="nt">em</span> <span class="p">{</span>
  2170. <span class="k">@return</span> <span class="err">$</span><span class="nt">px</span><span class="o">;</span>
  2171. <span class="p">}</span>
  2172. <span class="k">@return</span> <span class="o">(</span><span class="err">$</span><span class="nt">px</span> <span class="o">/</span> <span class="err">$</span><span class="nt">base-font-size</span><span class="o">)</span> <span class="o">*</span> <span class="nt">1em</span><span class="o">;</span>
  2173. <span class="p">}</span></code></pre></div>
  2174. </div>
  2175. <div class="code-block__wrapper" data-syntax="sass">
  2176. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="k">@function</span> <span class="nt">mq-px2em</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span><span class="o">,</span> <span class="err">$</span><span class="nt">base-font-size</span><span class="nd">:</span> <span class="err">$</span><span class="nt">mq-base-font-size</span><span class="o">)</span>
  2177. <span class="k">@if</span> <span class="nf">unitless</span><span class="p">(</span><span class="nv">$px</span><span class="p">)</span>
  2178. <span class="k">@warn</span> <span class="s1">'</span><span class="s2">Assuming </span><span class="si">#{</span><span class="nv">$px</span><span class="si">}</span><span class="s2"> to be in pixels, attempting to convert it into pixels.'</span>
  2179. <span class="k">@return</span> <span class="nt">mq-px2em</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span> <span class="o">+</span> <span class="nt">0px</span><span class="o">)</span>
  2180. <span class="k">@else</span> <span class="nt">if</span> <span class="nt">unit</span><span class="o">(</span><span class="err">$</span><span class="nt">px</span><span class="o">)</span> <span class="o">==</span> <span class="nt">em</span>
  2181. <span class="k">@return</span> <span class="err">$</span><span class="nt">px</span>
  2182. <span class="k">@return</span> <span class="o">(</span><span class="err">$</span><span class="nt">px</span> <span class="o">/</span> <span class="err">$</span><span class="nt">base-font-size</span><span class="o">)</span> <span class="o">*</span> <span class="nt">1em</span></code></pre></div>
  2183. </div>
  2184. </div>
  2185. <p>If the value happens to be unitless, the function assumes the value is meant to be expressed in pixels. At this point, an assumption may be risky so the user should be warned that the software did something that could be considered unexpected.</p>
  2186. <h2 id="errors">Errors</h2>
  2187. <p>Errors, unlike warnings, prevent the compiler from going any further. Basically, they stop the compilation and display a message in the output stream as well as the stack trace, which is handy for debugging. Because of this, errors should be thrown when there is no way for the program to keep running. When possible, try to work around the issue and display a warning instead.</p>
  2188. <p>As an example, let’s say you build a getter function to access values from a specific map. You could throw an error if the requested key does not exist in the map.</p>
  2189. <div class="code-block">
  2190. <div class="code-block__wrapper" data-syntax="scss">
  2191. <div class="highlight"><pre><code class="language-scss" data-lang="scss"><span class="c1">/// Z-indexes map, gathering all Z layers of the application</span>
  2192. <span class="c1">/// @access private</span>
  2193. <span class="c1">/// @type Map</span>
  2194. <span class="c1">/// @prop {String} key - Layer’s name</span>
  2195. <span class="c1">/// @prop {Number} value - Z value mapped to the key</span>
  2196. <span class="nv">$z-indexes</span><span class="o">:</span> <span class="p">(</span>
  2197. <span class="s1">'</span><span class="s2">modal'</span><span class="o">:</span> <span class="mi">5000</span><span class="o">,</span>
  2198. <span class="s1">'</span><span class="s2">dropdown'</span><span class="o">:</span> <span class="mi">4000</span><span class="o">,</span>
  2199. <span class="s1">'</span><span class="s2">default'</span><span class="o">:</span> <span class="mi">1</span><span class="o">,</span>
  2200. <span class="s1">'</span><span class="s2">below'</span><span class="o">:</span> <span class="mi">-1</span><span class="o">,</span>
  2201. <span class="p">);</span>
  2202. <span class="c1">/// Get a z-index value from a layer name</span>
  2203. <span class="c1">/// @access public</span>
  2204. <span class="c1">/// @param {String} $layer - Layer's name</span>
  2205. <span class="c1">/// @return {Number}</span>
  2206. <span class="c1">/// @require $z-indexes</span>
  2207. <span class="k">@function</span> <span class="nt">z</span><span class="o">(</span><span class="err">$</span><span class="nt">layer</span><span class="o">)</span> <span class="p">{</span>
  2208. <span class="k">@if</span> <span class="ow">not</span> <span class="nf">map-has-key</span><span class="p">(</span><span class="nv">$z-indexes</span><span class="o">,</span> <span class="nv">$layer</span><span class="p">)</span> <span class="p">{</span>
  2209. <span class="k">@error</span> <span class="s1">'</span><span class="s2">There is no layer named `</span><span class="si">#{</span><span class="nv">$layer</span><span class="si">}</span><span class="s2">` in $z-indexes. '</span>
  2210. <span class="o">+</span> <span class="s1">'</span><span class="s2">Layer should be one of </span><span class="si">#{</span><span class="nf">map-keys</span><span class="p">(</span><span class="nv">$z-indexes</span><span class="p">)</span><span class="si">}</span><span class="s2">.'</span><span class="o">;</span>
  2211. <span class="p">}</span>
  2212. <span class="k">@return</span> <span class="nt">map-get</span><span class="o">(</span><span class="err">$</span><span class="nt">z-indexes</span><span class="o">,</span> <span class="err">$</span><span class="nt">layer</span><span class="o">);</span>
  2213. <span class="p">}</span></code></pre></div>
  2214. </div>
  2215. <div class="code-block__wrapper" data-syntax="sass">
  2216. <div class="highlight"><pre><code class="language-sass" data-lang="sass"><span class="c1">/// Z-indexes map, gathering all Z layers of the application</span>
  2217. <span class="c1">/// @access private</span>
  2218. <span class="c1">/// @type Map</span>
  2219. <span class="c1">/// @prop {String} key - Layer's name</span>
  2220. <span class="c1">/// @prop {Number} value - Z value mapped to the key</span>
  2221. <span class="na">$z-indexes</span><span class="o">:</span> <span class="p">(</span><span class="s1">'</span><span class="s2">modal'</span><span class="o">:</span> <span class="mi">5000</span><span class="o">,</span> <span class="s1">'</span><span class="s2">dropdown'</span><span class="o">:</span> <span class="mi">4000</span><span class="o">,</span> <span class="s1">'</span><span class="s2">default'</span><span class="o">:</span> <span class="mi">1</span><span class="o">,</span> <span class="s1">'</span><span class="s2">below'</span><span class="o">:</span> <span class="mi">-1</span><span class="o">,</span><span class="p">)</span>
  2222. <span class="c1">/// Get a z-index value from a layer name</span>
  2223. <span class="c1">/// @access public</span>
  2224. <span class="c1">/// @param {String} $layer - Layer's name</span>
  2225. <span class="c1">/// @return {Number}</span>
  2226. <span class="c1">/// @require $z-indexes</span>
  2227. <span class="k">@function</span> <span class="nt">z</span><span class="o">(</span><span class="err">$</span><span class="nt">layer</span><span class="o">)</span>
  2228. <span class="k">@if</span> <span class="ow">not</span> <span class="nf">map-has-key</span><span class="p">(</span><span class="nv">$z-indexes</span><span class="o">,</span> <span class="nv">$layer</span><span class="p">)</span>
  2229. <span class="k">@error</span> <span class="s1">'</span><span class="s2">There is no layer named `</span><span class="si">#{</span><span class="nv">$layer</span><span class="si">}</span><span class="s2">` in $z-indexes. '</span>
  2230. <span class="o">+</span> <span class="s1">'</span><span class="s2">Layer should be one of </span><span class="si">#{</span><span class="nf">map-keys</span><span class="p">(</span><span class="nv">$z-indexes</span><span class="p">)</span><span class="si">}</span><span class="s2">.'</span>
  2231. <span class="k">@return</span> <span class="nt">map-get</span><span class="o">(</span><span class="err">$</span><span class="nt">z-indexes</span><span class="o">,</span> <span class="err">$</span><span class="nt">layer</span><span class="o">)</span></code></pre></div>
  2232. </div>
  2233. </div>
  2234. <p>What’s nice about a CSS preprocessor as popular as Sass is that it comes with a whole ecosystem of frameworks, plugins, libraries and tools. After 8 years of existence, we are getting closer and closer to the point where <a href="http://hugogiraudel.com/2014/10/27/rethinking-atwoods-law/">everything that can be written in Sass has been written in Sass</a>.</p>
  2235. <p>However my advice would to be to lower the number of dependencies to the strict minimum. Managing dependencies is some sort of hell you don’t want to be part of. Plus, there is little to no need for external dependencies when it comes to Sass.</p>
  2236. <h2 id="compass">Compass</h2>
  2237. <p><a href="http://compass-style.org/">Compass</a> is the main Sass framework out there. Developed by <a href="https://twitter.com/chriseppstein">Chris Eppstein</a>, one of the two core designers of Sass, I don’t see it dramatically losing in popularity for a while, if you want my opinion.</p>
  2238. <p>Still, I do not use Compass anymore, the main reason is that it slows Sass down a lot. Ruby Sass is quite slow in itself, so adding more Ruby and more Sass on top of it doesn’t really help.</p>
  2239. <p>The thing is, we use very little from the whole framework. Compass is huge. Cross-browser compatibility mixins is just the tip of the iceberg. Math functions, image helpers, spriting… There is so much that can be done with this great piece of software.</p>
  2240. <p>Unfortunately, this is all sugar and there is no killer feature in there. An exception could be made of the sprite builder which is <em>really great</em>, but <a href="https://github.com/filamentgroup/grunticon">Grunticon</a> and <a href="http://grumpicon.com/">Grumpicon</a> do the job as well, and have the benefit of being pluggable in the build process.</p>
  2241. <p>Anyway, I do not forbid the use of Compass although I would not recommend it either, especially since it is not LibSass-compatible (even if efforts have been made in that direction). If you feel better using it, fair enough, but I don’t think you’ll get much from it at the end of the day.</p>
  2242. <div class="note">
  2243. <p>Ruby Sass is currently going under some outstanding optimizations that are specifically targeted at logic-heavy styles with many functions and mixins. They should dramatically improve performance to the point where Compass and other frameworks might not be slowing Sass anymore.</p>
  2244. </div>
  2245. <h6 id="further-reading-28">Further reading</h6>
  2246. <h2 id="grid-systems">Grid systems</h2>
  2247. <p>Not using a grid system is not an option now that Responsive Web Design is all over the place. To make designs look consistent and solid across all sizes, we use some sort of grid to lay out the elements. To avoid having to code this grid work over and over again, some brilliant minds made theirs reusable.</p>
  2248. <p>Let me put this straight: I am not a big fan of grid systems. Of course I do see the potential, but I think most of them are completely overkill and are mostly used to draw red columns on a white background in nerdy designers’ speaker decks. When is the last time you thought <em>thank-God-I-have-this-tool-to-build-this-2-5-3.1-π-grid</em>? That’s right, never. Because in most cases, you just want the usual regular 12-columns grid, nothing fancy.</p>
  2249. <p>If you are using a CSS framework for your project like <a href="http://getbootstrap.com/">Bootstrap</a> or <a href="http://foundation.zurb.com/">Foundation</a>, chances are high it includes a grid system already in which case I would recommend to use it to avoid having to deal with yet another dependency.</p>
  2250. <p>If you are not tied to a specific grid system, you will be pleased to know there are two top-notch Sass powered grid engines out there: <a href="http://susy.oddbird.net/">Susy</a> and <a href="http://singularity.gs/">Singularity</a>. Both do much more than you will ever need so you can pick the one you prefer between these two and be sure all your edge cases—even the most nifty ones—will be covered. If you ask me, Susy has a slightly better community, but that’s my opinion.</p>
  2251. <p>Or you can head over to something a bit more casual, like <a href="https://github.com/csswizardry/csswizardry-grids">csswizardry-grids</a>. All in all, the choice will not have much of an impact on your coding style, so this is pretty much up to you at this point.</p>
  2252. <h6 id="further-reading-29">Further reading</h6>
  2253. <h2 id="scss-lint">SCSS-lint</h2>
  2254. <p>Linting code is very important. Usually, following guidelines from a styleguide helps reducing the amount of code quality mistakes but nobody’s perfect and there are always things to improve. So you could say that linting code is as important as commenting it.</p>
  2255. <p><a href="https://github.com/causes/scss-lint">SCSS-lint</a> is a tool to help you keep your SCSS files clean and readable. It is fully customisable and easy to integrate with your own tools.</p>
  2256. <p>Fortunately, SCSS-lint recommendations are very similar to those described in this document. In order to configure SCSS-lint according to Sass Guidelines, may I recommend the following setup:</p>
  2257. <div class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="c1"># For SCSS-Lint v0.32.0</span>
  2258. <span class="l-Scalar-Plain">linters</span><span class="p-Indicator">:</span>
  2259. <span class="l-Scalar-Plain">BangFormat</span><span class="p-Indicator">:</span>
  2260. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2261. <span class="l-Scalar-Plain">space_before_bang</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2262. <span class="l-Scalar-Plain">space_after_bang</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2263. <span class="l-Scalar-Plain">BorderZero</span><span class="p-Indicator">:</span>
  2264. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2265. <span class="l-Scalar-Plain">ColorKeyword</span><span class="p-Indicator">:</span>
  2266. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2267. <span class="l-Scalar-Plain">Comment</span><span class="p-Indicator">:</span>
  2268. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2269. <span class="l-Scalar-Plain">DebugStatement</span><span class="p-Indicator">:</span>
  2270. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2271. <span class="l-Scalar-Plain">DeclarationOrder</span><span class="p-Indicator">:</span>
  2272. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2273. <span class="l-Scalar-Plain">DuplicateProperty</span><span class="p-Indicator">:</span>
  2274. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2275. <span class="l-Scalar-Plain">ElsePlacement</span><span class="p-Indicator">:</span>
  2276. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2277. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">same_line</span>
  2278. <span class="l-Scalar-Plain">EmptyLineBetweenBlocks</span><span class="p-Indicator">:</span>
  2279. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2280. <span class="l-Scalar-Plain">ignore_single_line_blocks</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2281. <span class="l-Scalar-Plain">EmptyRule</span><span class="p-Indicator">:</span>
  2282. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2283. <span class="l-Scalar-Plain">FinalNewline</span><span class="p-Indicator">:</span>
  2284. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2285. <span class="l-Scalar-Plain">present</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2286. <span class="l-Scalar-Plain">HexLength</span><span class="p-Indicator">:</span>
  2287. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2288. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">short</span>
  2289. <span class="l-Scalar-Plain">HexNotation</span><span class="p-Indicator">:</span>
  2290. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2291. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">lowercase</span>
  2292. <span class="l-Scalar-Plain">HexValidation</span><span class="p-Indicator">:</span>
  2293. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2294. <span class="l-Scalar-Plain">IdSelector</span><span class="p-Indicator">:</span>
  2295. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2296. <span class="l-Scalar-Plain">ImportPath</span><span class="p-Indicator">:</span>
  2297. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2298. <span class="l-Scalar-Plain">leading_underscore</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2299. <span class="l-Scalar-Plain">filename_extension</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2300. <span class="l-Scalar-Plain">Indentation</span><span class="p-Indicator">:</span>
  2301. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2302. <span class="l-Scalar-Plain">character</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">space</span>
  2303. <span class="l-Scalar-Plain">width</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">2</span>
  2304. <span class="l-Scalar-Plain">LeadingZero</span><span class="p-Indicator">:</span>
  2305. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2306. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">include_zero</span>
  2307. <span class="l-Scalar-Plain">MergeableSelector</span><span class="p-Indicator">:</span>
  2308. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2309. <span class="l-Scalar-Plain">force_nesting</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2310. <span class="l-Scalar-Plain">NameFormat</span><span class="p-Indicator">:</span>
  2311. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2312. <span class="l-Scalar-Plain">convention</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">hyphenated_lowercase</span>
  2313. <span class="l-Scalar-Plain">allow_leading_underscore</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2314. <span class="l-Scalar-Plain">NestingDepth</span><span class="p-Indicator">:</span>
  2315. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2316. <span class="l-Scalar-Plain">max_depth</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">3</span>
  2317. <span class="l-Scalar-Plain">PlaceholderInExtend</span><span class="p-Indicator">:</span>
  2318. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2319. <span class="l-Scalar-Plain">PropertySortOrder</span><span class="p-Indicator">:</span>
  2320. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2321. <span class="l-Scalar-Plain">ignore_unspecified</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2322. <span class="l-Scalar-Plain">PropertySpelling</span><span class="p-Indicator">:</span>
  2323. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2324. <span class="l-Scalar-Plain">extra_properties</span><span class="p-Indicator">:</span> <span class="p-Indicator">[]</span>
  2325. <span class="l-Scalar-Plain">QualifyingElement</span><span class="p-Indicator">:</span>
  2326. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2327. <span class="l-Scalar-Plain">allow_element_with_attribute</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2328. <span class="l-Scalar-Plain">allow_element_with_class</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2329. <span class="l-Scalar-Plain">allow_element_with_id</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2330. <span class="l-Scalar-Plain">SelectorDepth</span><span class="p-Indicator">:</span>
  2331. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2332. <span class="l-Scalar-Plain">max_depth</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">3</span>
  2333. <span class="l-Scalar-Plain">SelectorFormat</span><span class="p-Indicator">:</span>
  2334. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2335. <span class="l-Scalar-Plain">convention</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">hyphenated_lowercase</span>
  2336. <span class="l-Scalar-Plain">class_convention</span><span class="p-Indicator">:</span> <span class="s">'^(?:u|is|has)\-[a-z][a-zA-Z0-9]*$|^(?!u|is|has)[a-zA-Z][a-zA-Z0-9]*(?:\-[a-z][a-zA-Z0-9]*)?(?:\-\-[a-z][a-zA-Z0-9]*)?$'</span>
  2337. <span class="l-Scalar-Plain">Shorthand</span><span class="p-Indicator">:</span>
  2338. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2339. <span class="l-Scalar-Plain">SingleLinePerProperty</span><span class="p-Indicator">:</span>
  2340. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2341. <span class="l-Scalar-Plain">allow_single_line_rule_sets</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2342. <span class="l-Scalar-Plain">SingleLinePerSelector</span><span class="p-Indicator">:</span>
  2343. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2344. <span class="l-Scalar-Plain">SpaceAfterComma</span><span class="p-Indicator">:</span>
  2345. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2346. <span class="l-Scalar-Plain">SpaceAfterPropertyColon</span><span class="p-Indicator">:</span>
  2347. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2348. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">one_space</span>
  2349. <span class="l-Scalar-Plain">SpaceAfterPropertyName</span><span class="p-Indicator">:</span>
  2350. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2351. <span class="l-Scalar-Plain">SpaceBeforeBrace</span><span class="p-Indicator">:</span>
  2352. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2353. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">space</span>
  2354. <span class="l-Scalar-Plain">allow_single_line_padding</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2355. <span class="l-Scalar-Plain">SpaceBetweenParens</span><span class="p-Indicator">:</span>
  2356. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2357. <span class="l-Scalar-Plain">spaces</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">0</span>
  2358. <span class="l-Scalar-Plain">StringQuotes</span><span class="p-Indicator">:</span>
  2359. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2360. <span class="l-Scalar-Plain">style</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">single_quotes</span>
  2361. <span class="l-Scalar-Plain">TrailingSemicolon</span><span class="p-Indicator">:</span>
  2362. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2363. <span class="l-Scalar-Plain">TrailingZero</span><span class="p-Indicator">:</span>
  2364. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2365. <span class="l-Scalar-Plain">UnnecessaryMantissa</span><span class="p-Indicator">:</span>
  2366. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2367. <span class="l-Scalar-Plain">UnnecessaryParentReference</span><span class="p-Indicator">:</span>
  2368. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2369. <span class="l-Scalar-Plain">UrlFormat</span><span class="p-Indicator">:</span>
  2370. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
  2371. <span class="l-Scalar-Plain">UrlQuotes</span><span class="p-Indicator">:</span>
  2372. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2373. <span class="l-Scalar-Plain">VendorPrefixes</span><span class="p-Indicator">:</span>
  2374. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
  2375. <span class="l-Scalar-Plain">identifier_list</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">base</span>
  2376. <span class="l-Scalar-Plain">include</span><span class="p-Indicator">:</span> <span class="p-Indicator">[]</span>
  2377. <span class="l-Scalar-Plain">exclude</span><span class="p-Indicator">:</span> <span class="p-Indicator">[]</span>
  2378. <span class="l-Scalar-Plain">ZeroUnit</span><span class="p-Indicator">:</span>
  2379. <span class="l-Scalar-Plain">enabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span></code></pre></div>
  2380. <div class="note">
  2381. <p>If you want to plug SCSS lint into your Grunt build process, you will be pleased to know there is a Grunt plugin for that called <a href="https://github.com/ahmednuaman/grunt-scss-lint">grunt-scss-lint</a>.</p>
  2382. <p>Also, if you are on the hunt for a neat application that works with SCSS-lint and the like, the guys at <a href="http://thoughtbot.com/">Thoughtbot</a> (Bourbon, Neat...) are working on <a href="https://houndci.com/">Hound</a>.</p>
  2383. </div>
  2384. <h6 id="further-reading-30">Further reading</h6>
  2385. <h1 id="too-long-didnt-read">Too Long; Didn’t read</h1>
  2386. <p>To sum up, we want:</p>
  2387. <ul>
  2388. <li>Two (2) spaces indents, no tabs;</li>
  2389. <li>80-characters wide lines;</li>
  2390. <li>Properly written multi-line CSS;</li>
  2391. <li>Meaningful use of whitespaces;</li>
  2392. <li>Quoted strings (single quotes) &amp; URLs;</li>
  2393. <li>No trailing 0, mandatory leading 0;</li>
  2394. <li>Calculations wrapped in parentheses;</li>
  2395. <li>No magic numbers;</li>
  2396. <li>Colors expressed in keywords &gt; HSL &gt; RGB &gt; hexadecimal;</li>
  2397. <li>Lists separated with commas;</li>
  2398. <li>No trailing comma in lists (since they are inlined);</li>
  2399. <li>Trailing comma in maps;</li>
  2400. <li>No selector nesting except for pseudo-classes and pseudo-elements;</li>
  2401. <li>Hyphen-delimited naming;</li>
  2402. <li>Extensive comments;</li>
  2403. <li>SassDoc-powered API comments;</li>
  2404. <li>Limited usage of <code>@extend</code>;</li>
  2405. <li>Simple mixins;</li>
  2406. <li>As few loops as possible, no <code>@while</code>;</li>
  2407. <li>Reduced number of dependencies;</li>
  2408. <li>Meaningful use of warnings and errors.</li>
  2409. </ul>