Conventions for Sass in Magento 2

SNOW.DOG, led by Bartek Igielski, have been working on a Sass port of the blank theme Less files. This work is spinning up a number of parallel discussion threads, some of which I thought worth sharing here, with the intent of getting community feedback.

Example discussion threads include:

  • Reviewing CSS class naming – will improved class names in the HTML simplify the Sass files? For example, should BEM be adopted for CSS class naming?
  • What do themes really need to be able to change? How much can be truly expected of a theme, versus themes being good starting points and some site specific tinkering being required.
  • What is the relationship between third party themes and extensions with respect to CSS?
  • Does Magento’s support for CSS file merging need to be improved?

This blog post proposes conventions for introducing Sass into Magento 2, taking into account the needs of solution partners, extension/theme developers, and merchants with and without access to developers.

Note that there is no change in Magento functionality required for this proposal – the proposal is purely conventions to be followed by developers. That means it can be adopted at any time for any version of Magento 2.

Note that the Less files shipped with Magento are not the focus of this discussion. This blog post focuses on how best to introduce Sass in a consistent way.

Sass in the Blank Theme

So what is SNOW.DOG working on exactly? Shipped with Magento is a set of Less files representing

  • A library of mixins for assembling CSS files, where changing a few variables (such as button styles) can consistently change the look and feel across the whole site.
  • A base set of CSS rules used by common UI patterns.

SNOW.DOG are rewriting this set of Less files in Sass, in part due to the popularity of Sass over Less, and in part with an eye to simplification while retaining “just enough” flexibility.

Another goal is to avoid any customizations like the custom Magento “//@magento_import” Less directive, making it easier to use standard frontend development tools. (I have a number of previous posts in this area on my blog, such as on Gulp in Magento 2.) Instead of locating files across all modules, each module that needs to add additional CSS rules should instead add a new CSS file to hold those rules.

Autoprefixing

One of the topics that came up in the SNOW.DOG design was whether the Sass files can assume “Autoprefixer” is being used. (The same holds for any other “cool” CSS processing tools.) Autoprefixer is a utility (developed in NodeJS) that parses CSS files, expanding standard property names to all browser specific property names supported by older browser versions. For example, “-webkit-border-radius” was supported by the WebKit rendering engine before “border-radius” became officially accepted by the CSS standards body. So to increase compatibility across browsers, it is recommended to set “-webkit-border-radius” whenever “border-radius” is set.

This is what Autoprefixer does automatically – it reads in the standard property names and injects all known variants supported by older browsers. The benefit of Autoprefixer is a frontend developer can focus on a simple, clean CSS file. They do not need to worry about remembering all of the variations of property names.

So what did developers do before Autoprefixer? Mixin libraries like the Magento UI Library and the Sass Compass library used mixins to set properties. Instead of setting “border-radius” directly, a mixin is defined to set the property. This mixin can then set all of the variations. This works, but the Sass source file looks less clean as a result, and frontend developers could make a mistake of setting a property directly instead of using the provided mixin, resulting in not all variations being set.

Unfortunately, Autoprefixer is only available in JavaScript (NodeJS). Magento currently compiles CSS files on demand from Less and Sass. Adding a Magento dependency on Autoprefixer in the built in Less/Sass compilation pipeline is not acceptable as shared hosting providers do not provide the ability to install new tools such as Autoprefixer. Hence the following is based around developers needing to install and use NodeJS Sass compilation tools such as Grunt and Gulp, not Magento itself.

Let’s explore the rules.

Proposed Rule for Extension/Theme Developers – Ship Sass and Precompiled CSS

It is proposed that extension/theme developers on Magento Marketplace follow a number of new rules. The first rule is as follows:

  • Extensions/themes should be shipped both with Sass files for any new CSS needed by the extension/theme, plus the compiled CSS generated from that Sass file.

Magento will use the supplied CSS file when the extension/theme is loaded. This is because Magento only attempts Sass compilation if it finds a Sass file but no CSS file.

This rule implies the extension/theme developer is expected to install NodeJS and frontend CSS compilation tools like Grunt or Gulp. They use these tools to perform the Sass compilation (including the Autoprefixer), then include the generated CSS with the shipped product.

This is not what is done today with Less files in the Magento UI library. The Less files are compiled on demand, meaning themes do not need to ship CSS files – only changes to Less variables to change button colors or similar.

Similarly, the rule implies simple sites built purely from Marketplace purchases will not perform any Sass compilation. They will just use the supplied CSS files. This allows advanced Sass compilation tools to be used when developing for Magento, without need for low end merchants to have to worry about such tools.

It also means that deployments will be faster as there is no Sass compilation phase during deployments. (And the crowd goes wild!) The native CSS files are used instead. All such compilation will occur during development.

A limitation of this approach however is it is not possible to have locale specific CSS generated from Sass files. Locales are only known for a specific merchant site.

Question #1: Is the limitation of no per-locale Sass variations considered acceptable?

Proposed Rule for Extension/Theme Developers – Avoid Adding CSS Class Names that Themes Should Redefine

The next rule for extension/theme developers is:

  • Try to use existing CSS class names to pick up colors for buttons etc that should be themed, rather than introducing additional CSS classes styled using existing Sass mixins/variables.

The reason for this rule is if an extension introduces a new CSS class name, themes in the Marketplace will not know of this name and so will not override the CSS with the new desired styling. Themes will only override the base Magento class name styles.

Question #2: Is it acceptable that extensions may ship with Sass files that use the default Sass rules and variables, but theme changes to Sass variables (e.g. to change a button color variable) will not be by default picked up. A developer will be required to recompile the Sass file in such cases.

Sometimes it is the correct to introduce new CSS class names. If a theme is not intended to change the supplied styling, then using new CSS class names is recommended.

Merchants Without Developers

For merchants building a site without developers, they will purchase extensions and themes from the Magento Marketplace and add them to the site. No Sass compilation will be required.

If any tweaking of the end result is required (e.g. the color of an extension button is incorrect), it will be required for a theme to be created to add/override the CSS rules to get the correct styling. One area of further exploration is how hard is it for non-developer merchants to create a simple CSS based theme, so small CSS tweaks or fixes can be applied. No NodeJS tools, just native CSS files. Such cases would help fix specific problems without recompiling the underlying Sass file.

Proposed Rule for Merchants with Developers – Recompile Sass Files to Pick Up Variable Changes

For merchants with developers,

  • The developers can build a new extension or theme which recompiles the Sass files of an existing theme or module. These developers, like extension/theme developers, would be expected to install NodeJS based frontend tools.

This would be common for theme developers.

This is why extension developers and theme developers should provide the Sass files inside extensions/themes, even though normally the precompiled CSS files will be shipped. Sass variables can be changed in this process, to change button colors etc. New CSS files would be created that override the original CSS files.

Conclusions

In summary, the proposed conventions for Sass based CSS development with Magento is

  • Ship extensions/themes with compiled CSS files so production sites can just use the CSS files.
  • Developers would install NodeJS, change Sass variables, then recompile the CSS files. This is a development activity, not a deployment activity. (I should also note that Magento is working on a standard Docker image for development that includes NodeJS preinstalled.)
  • Themes purchased from the Magento Marketplace will replace the default set of CSS files, rather than just change a few Sass variable settings with Magento recompiling the CSS files from the Sass files.

For example, in Magento Cloud, an implication of the above would be that the generated CSS files would be committed by developers to the git repository, rather than CSS compilation occuring during the build and deployment phases. The developer will be expected to install NodeJS and Grunt/Gulp and use them during frontend development, not rely on Magento performing Sass compilation on demand for CSS files.

It is a tricky balancing act allowing frontend developers to use the tools they love. Further, there seems to be still rapid change in the area of frontend development. As such, building tools such as Autoprefixer into Magento seems dangerous – new tools will be constantly appearing. As a result, delivering raw CSS files with modules seems preferable. Simple sites and merchants do not need to worry about such technologies – such technologies would be left to developers.

My main question in my mind is how well will themes replacing the base set of CSS files work (by recompiling the provided Sass files after any Sass variable changes). And will it be acceptable that new CSS classes introduced by extensions will not pick up such changes by default – a developer will need to recompile the files.

The reason I believe this may be acceptable is based on feedback that any sophisticated site is likely to need some tweaking by development resources. Keeping Sass and Autoprefix compilation out of Magento by shipping plain CSS files, and requiring developers to install and use NodeJS and similar tools instead, may be a better balance allowing frontend developers to use modern tools.

I do have another concern is that extensions and modules may need guidance around standardization of Sass compilation to avoid different extensions requiring different tools to be used. So the rules above may need to be extended to the Sass compilation instructions.

Well, over to you the reader! Are the positives worth the negatives? Feedback in the comments below welcome!

25 comments

  1. Magento 2 its work great but the less and the deployment process is slow :/

    I think its a good idea to put SASS support even if some theme will be needed to change there css because magento 2 its on stable less then a year so its not that bad .

    For now – i cant use it when i develop sites at magneto 2.1.1 because its not on the official repo .

    I will wait until it will be at magento 2 official repo and i hope it will be soon .

    I heard a lot of magento developer who develop on M2 and this deploy process and the “grunt watch” really make the development slow.

    I will follow this post and your blog for getting more news about it.

    Thanks

    1. Deploy has been improving (with more coming RSN). Yes, the deploy process was too slow.

      This proposal does not actually require any change to Magento by the way. Because you are really just using CSS – we just have a standard way to do the Sass compilation. We do not need Sass built into Magento for this proposal to kick in.

      Note that if you use Grunt/Gulp to compile Sass, that will decouple it from the Magento deployment workflow. It will just be CSS files as far as Magento is concerned. So a large slab of static asset compilation goes away. So this change may also help the deployment performance.

      But we are definitely investigating getting this all into the core – even if it’s just standardization. SNOW.DOG have been leading that effort as a community project, but there have only been a small number of other people helping to date.

      1. I use only grunt and less like it been written on the official doc devdoc.magento.com

        On magento 2 there’s is a lot of bug that i need to handle and yet – i develop a site on production mode (https://www.pilo.co.il/).

        It was extremely hard to develop it because the deploy process and i cant handle issues on beta version of SNOW.DOG blank theme.

        its too risky to use it – this platform is super hard for FE and i can understand its for the best and i really up-vote for it!

        On there repo on README.md(SNOW.DOG)


        Current status

        Theme is ready to use as Composer package with Magento 2. Still a lot of things needs to be fixed or polished, but it’s definitely working 😄

        I will wait after you will insert it on the repo after all the test will be completed.
        In general, i think its a great idea to use sass and gulp if we can to make FE development more easy but if the solution they offer not work 100% so as a Full stack developer – i will need to wait.

        i will follow this post and comments..

        Thanks

      2. Gotcha, thanks for the feedback. Yes, this whole thread is around getting some feedback before merging it in and making it standard. But that is a little off yet.

  2. Gut reaction: every theme or extension developer (probably) already includes both compiled CSS and source Sass/Less by default (because why not, and because people freak out when things don’t look proper out of box).

    Developers should have no expectation of not having to compile code locally — especially if the platform is moving toward not compiling on deployment for the benefit of developer experience. I think that’s the right move.

    For me part, I think most developers will establish their workflow for customizations and it won’t follow what works for sites assembled via the Marketplace. The needs are just too different, so I would aim for untethering the developer experience and keeping the Marketplace experience as close to W3C spec as possible (i.e. plain CSS). Let the devs go as wild as the project demands.

    — — — — —

    Q1: Is the limitation of no per-locale Sass variations considered acceptable?

    A1: Absolutely yes. We’ve had need to develop a site with different CSS per locale. When that could have been the case it was always a better solution to generalize or simplify to reduce the workaround to fit all locales. This is far more desirable as a developer and maintainer than writing per-locale code.

    — — — — —

    Q2: Is it acceptable that extensions may ship with Sass files that use the default Sass rules and variables, but theme changes to Sass variables (e.g. to change a button color variable) will not be by default picked up. A developer will be required to recompile the Sass file in such cases.

    A2: If a *useful and extensible* naming convention exists, both themes and extensions will benefit from re-using it. But if those conventions are poorly crafted or missing, I’d have zero reservations as a theme or extension maker in abandoning them or creating my own. In many cases namespacing custom code is simply a better practice than aiming for extreme re-use because it’s more maintainable and lighter overall by breaking ties to something that someone else may modify and break unto you.

    — — — — —

    Q3: If any tweaking of the end result is required (e.g. the color of an extension button is incorrect), it will be required for a theme to be created to add/override the CSS rules to get the correct styling. One area of further exploration is how hard is it for non-developer merchants to create a simple CSS based theme, so small CSS tweaks or fixes can be applied. No NodeJS tools, just native CSS files. Such cases would help fix specific problems without recompiling the underlying Sass file.

    A3: Effectively it’s asking how can we let non-developers write CSS exactly how developers never want maintain CSS again. Any reasonably complex site (which I believe every Magento site is) using patterns with inheritance is already too complex to override with simple CSS tweaks. It’s the wrong approach from the outset to try to simplify something that is ordered very differently for the developer experience. The non-developer can’t simply and correctly use specificity anymore to change a complex CSS system without breaking it outright (especially in ways they aren’t aware of immediately) or by making the site worse to develop/maintain in the future. I just don’t see small CSS tweaks having a place in Magento by non-developers. No client has ever asked for this.

    1. I think the proposal is basically saying ship CSS files, and have Sass available for developers who want to do something different.

      Yes, cleaning up the Class names is another thread we are looking at. Bartek had a poll in the forums where BEM won pretty convincingly, so we have “adding BEM to our PHTML files” on the backlog to investigate. That really feels like a precursor to releasing the Sass files, so they can take advantage of improve style names (and possibly some PHTML tweaks).

      But there is a low end segment of the market which I don’t think is really “in” the community. They spin up a site, buy a theme and a few extensions, and get on with life. They don’t care that it’s Magento – they care about there business. I get the feeling this low end is a silent but large segment, so trying to look after them best as possible.

      But this proposal is making it a little worse for the bottom end in favor of the bigger portion of “real” developers.

      So overall I think we are just agreeing with other.

    2. Another interesting question is whether we could crowd source getting BEM compatible class names in (as a coordinated event to give those PR’s priority etc). That assumes we can (1) get enough volunteers to tackle a few PHTML files, and (2) the rules are easy enough that we can spread out the load and end up with a good quality result.

    3. I served theme buyers for longer (7y) than clients (6y), and the best summary of them is they will pay product makers to help tweak/integrate where they won’t pay freelancers or agencies. Almost nobody thought they could do it alone or held that belief persistently and continued to use Magento. The theme/extension ecosystem doesn’t absorb that work, and neither do agencies/partners so they likely scrubbed out.

      Regarding BEM, the hard part is not writing class names in BEM style — it’s understanding what makes a good pattern/component and how those pieces are composable across many interface scenarios. We’ve never sat down and written patterns preceding design. We always prototype a feature we need and then extract patterns from it and normalize into what we already understand/use.

      That will make converting what M2 already does challenging I think because in M1 it was unclear exactly how many patterns were utilized across the entire application. In M2 the components appear to be very configuration heavy with Less variables rather than being established via their use case. That makes it hard to know what of all the config must be supported or was just created for potential use’s sake. At a glance, that weight makes the patterns look far less maneuverable than I like to see in a pattern library.

      Caveat: I still have very little practical M2 experience for how this all meshes together.

      1. 7yrs? Okay, you win the theme debate! ;-). Which if I understand is good news

      2. Take 2 (stupid iPad). If I understand what you are saying is there is no reason to get too concerned about “clever use of variables for themes”. Just ship prebuilt CSS files so something happens out of the box, and ship the Sass files so developers can recompile and do what they need. The market is just not that sophisticated, so don’t overthink the problem. Am I getting that right?

      3. Yeah, basically. The biggest pain point has always been telling a customer buying add-ons that they need a developer to make it all work. At some point it’s just necessary, and typically the blame falls on the last module that reveals the conflict so it’s tough. You hardly ever have issues if you’re the first module being installed.

  3. lorenzost · · Reply

    So we are going toward a decoupled css generation? :happy:

    1. That is what is being explored. Do the benefits outweigh the restrictions. So responses like “happy” are actually useful! Thx!

  4. The only one concern is on committing pre Minifyed css – often get merge conflicts as it’s hard for git to merge a ‘single’ line style sheet. (Find this a lot with 1.14) but we cope it’s not a massive deal – and I’m not sure there’s really anyway round it? Unless the minification comes on deployment but as has already been mentioned deployment is a PAINFULLY long experience so anything to prevent that is great.
    But my opinion of the current LESS implementation was it felt like you were pandering to non coders with the idea that they could just change a couple of less vars and change a few colours etc.

    1. Could you explain a bit more why you need to merge different CSS commits? If needed, I can see why it is problematic. I just don’t quite get why merges (of different commits) would be required. Or is it just committing new versions of the gives GIT a hard time?

      1. If 2 seperate branches are working on 2 seperate SASS files but both merging into the same branch. – if they’re both commiting minifyed CSS it seems to often have trouble trying to auto merge them once one has gone in because its all on one line. But simply just pulling develop and recompiling instantly sorts it, but its always a step – its not a big deal, just saying it happens.

      2. Gotcha, thanks. That makes complete sense.

    2. I agee with andy. If you have a team of people working on a theme often you have to merge different branches that have worked in different areas, so probably their sass/less files won’t have conflicts. But the compiled css will. This disrupts the workflow of tools like Gitlab or Bitbucket and forces a manual merge (you only have to recompile css from scratch, but it is very tiring when you have to do this several times a day). The “git way” to do this kind of things is to compile at deploy time.

      There is indeed a problem with Magento deploys. I think the team doesn’t have a clear idea of the best deploy strategy to follow.

      My Magento2 websites take about 10 minute for every deploy. Obviously I can’t put them in maintenace mode for all that time (someone suggested that in a github issue, but it is clearly unacceptable). So it is clear that most of the deploy must be ran off-stage.
      How? Using tools like Capistrano. When using such tools you can achieve code compilation at deploy time. But, in this case I don’t see why such stances like “autoprefixer is unacceptable”. If css compilation is decoupled from Magento then this is not a Magento problem anymore.

      You say… Magento 2 in shared hosting can’t run node. But who on earth may want to to run a Magento2 instance on a shared hosting? This is not a css only problem, Magento2 needs to compile di and several other things. I can’t call my provider and say “hello, please run setup:upgrade on my website” every time I update a module. I think that shared hosting should not be considered by the team as a priority. Same is for “merchant without developers”. You can’t use magento without developers… and good developers, because Magento2 is hard.

      The greatness of Magento is customization. Merchants want integrations with their systems, custom functionalities, personalized checkout flow… and so on. Magento isn’t Prestashop, you can’t just install things from the marketplace and let them work. I think that Magento2 should not be considered as a “out of the box” platform. So let’s prioritize developers needs over a “do it yourself” mind.

      1. Thanks for the feedback. FYI, we are currently working on trying to get the DB dependencies out of the “build” phase, so you can do it on a separate machine, and get the deploy time down.

    3. Unfortunately Alan cut out a one point from our talks about improving development/deployment pipeline, which is important for solutions providers.
      IMO there should 3 ways to handle styles changes:
      1. Do change directly in CSS is you are not into SASS
      2. Do change in SASS, compile localy, push to repository and use precompiled CSS on production
      3. Mage changes in SASS, do not keep any CSS in repository and compile everything on demand (i.e. during deployment), but as part of Magento core, not separate module like Frontools. You gonna need NodeJS installed server side (that’s why this is not an option for all users). It will works like LESS currently, but ofc a lot faster 🙂

      1 and 2 is designed for low-end market and 3 for solutions providers with serious servers, development team etc.

  5. do you have rough target date for magento-created docker project? I’ve been using community versions since 1.14 and magento really should support docker 🙂 🙂

    1. It’s an active work item at present. We have a mix of requirements that we are trying to meet all at the same time. So it’s not so much finding the right things to install, it’s more like “what is the experience to get sample data loaded”, “does it work well with Magento Cloud”, etc.

      I am talking at Magento Live Australia in November on “Developer Experience” stuff, so I sure hope it’s going to be ready by then!

  6. Hey Alan,

    As an agency we have previously developed a “base” theme that we use as a starting place for many of our M1 projects. This starter theme was a collection of template overrides that cleaned up some of the core templates when needed, and a set of SASS files to give us basic structure, functionality and made them responsive.

    There have been a few struggles with inconsistencies in class naming, template structure and javascript initialization in M2. From module to module, the approach to frontend can often be quite different.

    For this reason, the idea of reworking the core templates in BEM would be a welcome change, specifically for consistency of approach in the core templates and giving us a good foundation to build from.

    Backward compatibility is a concern however, if BEM is added to the core templates. It would leave many of our existing projects without forward compatibility.

    It also means that until we have an answer to how BEM might be implemented, and how changes to the frontend infrastructure in general are going to happen, we cannot move forward with building our own re-usable starter theme.

    Another concern with implementing BEM is that it is not useful if it isn’t done across all modules, as otherwise you have a mess of different CSS approaches. So for it to be a successful change it would have to touch all areas of the core templates.

    The last point comes from experience in trying to implement BEM in M2 ourselves previously. We found that BEM adds various types of unexpected overheads, specifically relating to the Magento 2 infrastructure.

    For example, often a bespoke design calls for moving some parts of a template around, which can make the BEM class names incorrect. For example a product-info__name doesn’t make sense if you move the name outside of the product-info block. Seems simple, just change the class name;

    But sometimes those class names are set inside layout XML, and it’s not always easy to trace back where a class name comes from, especially if it has been overridden or changed by other modules.

    Sometimes to properly understand the changes you’re about to make, you can have a handful of CSS, Layout XML and template files open, and it can be quite a nightmare for something as simple as changing a class name on a div.

    I don’t know that there is a good solution to that particular issue, but it’s worth considering, as depending on the profile of your agency’s employees, it can either make a frontend developers job really difficult (as they shouldn’t need to be aware of Layout XML and block models to write CSS and templates), or you need to have generalists who can do both, lest you bother a backend developer with something like changing one class name during a features development. Currently we have a great deal of excellent generalists with some specializations, but as a team grows, hiring more and more generalists becomes less realistic.

    1. So do you have a recommendation based in your experience?

  7. For backward compatibility with existing projects, we had thought that it would be good for the templates implementing BEM to be a set of new templates inside a theme, that could be used by child themes if they choose to. That would mean Magento would need to maintain the BEM and non-BEM templates, and that may not be ideal.

    In regards to issues with finding class names in XML, similar issues in M1 were helped by good tooling, such as CommerceBug/Layout Helper, and AOE_People’s Advanced Template Hints module. Normally once you’ve found “the right template” that’s that, change at will.

    But it can be trickier to find all the XML files involved in making the final combined XML layout that affects your current container, so making it easier for a developer to find the right XML file to change would help bridge the gap between a frontend task and a backend task.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.