Why we started using the Stylus preprocessor in Yandex.Mail, and also about the library that helps you live with IE. Getting to know Stylus

Today I want to talk about why and how we came to use the Stylus preprocessor in the development of Yandex.Mail, and also describe the method we use for working with styles for IE. It is very easy to implement using preprocessors and makes IE support simple and convenient. We designed for this special library, which we will also share - if-ie.styl.

This is only the first article in a series of articles about using the Stylus preprocessor in Yandex.Mail, which we are preparing for publication.

How we came to use preprocessors Although outwardly Yandex.Mail looks like a single-page application, inside it contains a huge number of various blocks, their modifications and contexts in which these blocks and modifications may appear.

In addition, it already has more than thirty design themes. There are themes with a light background and with a dark one, there are themes that differ from each other only in colors, and there are also those in which almost the entire interface is molded from plasticine by hand (http://habrahabr.ru/company/yandex/blog/110556/ ). Some topics have only one background image, and in others the background may change - randomly or depending on the time of day and weather.

Because of all this, there are many variations. visual representation interface, which forces us to approach the development process a little differently and look for tools that are more suitable for solving the problem.

When we first launched the neo2 interface, we chose a solution that was familiar to us - the Template Toolkit 2 template engine, with a somewhat non-standard scenario for using it to generate CSS rather than HTML. At first we only needed variables, but over time the topics became more complex, and in the end it turned out that such a tool was inconvenient. Cumbersome syntax, lack of specialized functions CSS functions and a general feeling of using the tool for other purposes made us look for other options. We realized that we couldn't do without a preprocessor.

Choosing a preprocessor We chose between three options: Sass, Less and Stylus. The process was quite simple: we took several existing blocks, and then tried to redesign them using each of the preprocessors.

There are many more very different useful things in Stylus, but it was the ones mentioned above that made us choose it in favor.

Of course, in addition to the advantages, the Stylus also has disadvantages. And the main one is flexible syntax - the authors of the preprocessor consider it its main advantage. In pursuit of flexibility, they completely implemented only the syntax based on indentation, while the “a la CSS” option is somehow screwed on top, and it won’t be possible to just take and rename .css to .styl - not all CSS writing options will work and in Stylus. But we decided that the capabilities that this preprocessor gives us make its shortcomings less significant, so we had to put up with some of the capriciousness of the parser (and start using indentation-based syntax).

Summing up the story about the choice, it is worth noting that Sass and Stylus are two almost equivalent options. Each of them has its own advantages and unique features, as well as disadvantages. If you are already using one of these preprocessors and are satisfied with everything, great, you don’t have to think about looking for a new one. But if you are just approaching the choice or you feel overwhelmed with the preprocessor you are using, try comparing all the options. The best way To do this, try on each preprocessor for its own task. Having developed part of your project on each of the preprocessors, you will understand which of their capabilities are important to you and which are not. Just don’t forget that a preprocessor is not just a different syntax, but also a different approach: with such a redesign, you can at the same time refactor the code, doing something more optimal than it was with simple CSS.

However, we need to tell you about one more function that turned out to be very useful for us as part of the thematicization of Yandex.Mail. This is the rgba-ie function. In fact, this function could just be called rgba , but Stylus has a bug: functions defined in JS cannot be overridden in the same way as those defined in Stylus, so we had to create a new one.

What is she doing? Older IEs do not support color values ​​specified in rgba format. Therefore, usually developers either specify the corresponding colors twice - first for old IE in the usual hex format, and then for all normal browsers in the desired rgba - or use modernizr and, using it and the .rgba class, set the corresponding colors where needed. But for fallbacks in IE, each time we still have to calculate the approximate color of what we will degrade it into. Most often this will be the desired color overlaid on top of the page background or the middle element background, with an rgba color applied above it.

The rgba-ie function from if-ie.styl greatly simplifies this task: duplicating the capabilities of the regular rgba function, we get another optional parameter that can be passed to the function - the background color for the fallback. By default, this parameter is set to #FFF .

Simple example:

Foo color: rgba-ie(0,0,0,0.5)

In regular browsers this color will be the usual rgba(0,0,0,0.5) , but in IE it will turn into #808080 - that is, the corresponding color overlaid on top of white.

More complex example, with the target background as the last argument (and using one of the Stylus features - the ability to specify instead three digits r , g and b color in hex):

Foo background: rgba-ie(#FFDE00, .42, #19C261)

In this example, for normal browsers the color will be rgba(255,222,0,0.42) , but IE will get the correct #7ace38 .

At the same time, it is possible to set the default fallback using the $default_rgba_fallback variable.

As a result, you can greatly simplify your life if you use the rgba-ie function instead of the usual rgba - in this case you will almost not have to remember about IE.

Tags:

Add tags

If you're part of the Front-End scene, you may have heard of Stylus, a distant cousin of the Sass preprocessor language that no one really knows. Like Sass, Slylus is a CSS preprocessor written in Node.js. According to the GitHub web service, it defines itself as:

[…] revolutionary new language, which provides an efficient, dynamic, and expressive way to create CSS.

Well, let's say that the use of the word "revolutionary" is a little exaggerated here. But everything else is true. "What? Another one?” - you ask. “Kind of,” I’ll answer. But Stylus is not a new language at all. It began its existence around the beginning of 2011, but, as I noticed, opinions about it vary quite a bit. By the way, did you know that last changes on the Mozilla Developer Network were made using Stylus? David Walsh, who worked on the project, also wrote about how to get started with Stylus.

So what are the advantages of Stylus over Sass? Firstly, it is developed based on Node.sj, which is a plus for me personally. While it's great that you can use Sass in a Node workflow thanks to the Sass wrapper for LibSass, the same cannot be said for LibSass written in Node.

Additionally, Slylus has an extremely flexible syntax, which can be good or bad depending on the project, the team, and the tendency to adhere to strict coding principles. I think malleable syntax is a good thing, as long as you don't put too much logic into the stylesheet, and put the code in before committing to it.

In general, Stylus and Sass support quite a lot of the same features; you can take a look at full list Stylus features, but don't expect anything groundbreaking (although there are a few advanced features). Slylus also supports a lot of syntax features, although the outlines are much more blurred than in Sass: you can write in different styles however you want (indented, CSS styled) and you can mix and match in one style (the parser for this must have been fun to write).

So what do you think? Want to try?

Begin

As noted earlier, Slylus is written in Node.js so that we can install it like any other npm package:

$ npm install stylus -g

From there, you can hook it up to a Node worker process with using JavaScript API, or you can use the command line command line executable to compose style sheets. For the sake of simplicity, we will use the tool command line Stylus, but feel free to borrow it from Node script, Gulp or Grunt

stylus ./stylesheets/ --out ./public/css

The previous command tells Stylus to collect all Stylus styles (.styl) from the stylesheets folder and collect them in the public/css folder. Of course, you can also look at the directory if you want to make changes:

stylus --watch ./stylesheets/ --out ./public/css

Writing styles in Stylus

If you're just getting started and don't want to overwhelm yourself with new syntax, know that you can write simple css in the .styl file. Since Stylus supports standard CSS syntax, you can start with CSS code, only to strengthen it a little.

Basic syntax

As for the syntax itself, almost everything is optional. Curly braces: why bother? Colons: come on! Commas: yes, who needs them! Parentheses: please. Below is ideal correct code Stylus:

Foo .bar color tomato background deepskyblue

Something of a violation at first glance, but we can get used to it, especially when syntactic markers are available. As you probably guessed, the previous code compiles to:

Foo, .bar ( color: tomato; background: deepskyblue; )

Variables

The most commonly used function from CSS preprocessors should be able to define variables. It's no surprise that Slylus offers this too. Although unlike Sass, they are expressed with an equals sign (=) rather than a colon (:). Additionally, the dollar sign ($) is optional and can be safely omitted.

//Defining the variable `text-font-stack` text-font-stack = "Helvetica", "Arial", sans-serif; // Use it as part of the `font` body property font 125% / 1.5 text-font-stack

Now there's something Stylus does that Sass or any other preprocessor doesn't: look up the value of a property. Let's say you want to apply a negative left margin of half width; in Sass you'll have to store the width in a variable, but not in Stylus:

When using @width, we tell Stylus to get the width value

properties of the current block, treating it as a variable. Quite simple! Another interesting option usage is to output the property depending on whether it was previously defined:

Foo // ... other styles z-index: 1 unless @z-index

In this case, z-index will have a value of 1, unless .foo already had one set value For z-index properties. Paired with mixins, this will be a strong move.

Mixins

Speaking of which, let's define what a mixin is, since it's probably one of the most popular Sass features! The Stylus admixture does not need a specific keyword; it is a mixin if it has parentheses (empty or not) at the end of its name.

Size(width, height = width) width width height height

Just like in the first case, to include a mixin, you do not need special syntax, such as @include or +:

Foo size(100px)

You can even omit the parentheses if you want, in which case it will look like you're completely using a standard (not yet) CSS property. This mechanism is called transparent impurities, since their inclusions are invisible.

Foo size 100px

This may seem like an unnecessary gimmick at first glance, but this feature actually allows authors to extend standard CSS syntax. Consider the following overflow mixin:

Overflow(value) if value == ellipsis white-space nowrap overflow hidden text-overflow ellipsis else overflow: value

If given value is ellipsis, it prints the well-known declaration triplet needed to have one line overflowing with ellipses. Otherwise, she prints set value. Here's how you'll use it:

Foo overflow ellipsis

And this will give:

Foo ( white-space: nowrap; overflow: hidden; text-overflow: ellipsis; )

You have to admit, this is a pretty cool trick. Although it can be confusing (and possibly dangerous); be able to expand the standard CSS properties With additional meanings actually an interesting concept.

If you want to pass some content to a mixin, @content style, it's possible through a (block) variable. During inclusion, you only need to prefix the mixin name with a + to give it additional content.

Has-js() html.js & (block).foo +has-js() color red

This code compiled to:

Html.js .foo ( color: #f00; )

The last and very interesting feature Stylus mixins: They always have a local arguments variable containing all the arguments (if any) that are passed to the mixin when they are included there. This variable can be manipulated and treated like an array, for example to retrieve the value at specific indexes using the combination [..] as in JavaScript.

And in conclusion…

Going through all the features and syntax tricks from Stylus would be too long, and I think we've already done a decent introduction, enough to get us started at least!

As you can see, the Stylus is very flexible. Of all the tools out there that can help you write CSS, Stylus is by far the only one that brings CSS closer to a real programming language.

Note that Stylus also has its own framework, just like Sass has Compass, and it's called Nib. Nib are tools that provide additional helpers and cross-browser support for Stylus mixins.

Some people might like it and some people might not. Although my advice is to be very strict with the syntax. Working with such tolerant syntax may not always be bliss. Either way, it's nice to see some healthy competition for Sass.

CSS is an intentionally simple language. With the proliferation of complex web applications, the emergence of front-end developer positions, and the growing number of newfangled requirements, this simplicity is quickly evaporating. For the uninitiated, CSS preprocessors (particularly Sass, LESS, and Stylus) expand your styling capabilities with additional functionality like variables, nesting, and mixins—giving you much more control over big amount styles.

There is a shortage of articles promoting the use of preprocessors and providing quick guide according to them, in last years no, and many points were already quite well described. So let's focus on what is often overlooked and see what can be done against terminal solutions.

Introduction (optional)

As noted in the introduction, things like Sass, LESS, and Stylus provide us with additional functionality on top of CSS, but files written in these languages ​​must be compiled into CSS before the browser can try to parse anything in them. IN general case, the compilation process is automated in such a way as to negate any impact on workflow.

Using any of the listed preprocessors, you can benefit from the following:

Expressiveness: Each of the preprocessors contains a set of time-saving conventions, the essence of which lies in the optionality or rejection of various punctuation rules. Depending on your preferences, styles can be freed from parentheses, semicolons, and/or regular commas. Plus, they all support nesting of selectors.

Advanced functionality: These languages, to varying degrees, offer additional features to shape our styles; This includes mixins (pieces of reusable code that can take optional arguments), extensions (class inheritance), and variable support.

Add-ons: to expand the standard arsenal, various add-ons are widely used. Sass has Compass, Stylus has Nib, and while it's a different story, Bootstrap, which needs no introduction, is built with LESS.

Real benefits

In fact, the main benefit of preprocessors lies in less effort - not physical (press keys less often), but mental. Preprocessors give you effective opportunity remove some of the tedious load on the mind and switch less between various applications, which is typical for front-end development. Do you have a frequently used color meaning? Store it in a variable instead of hunting for it around the project or storing it in your memory. Need a predictable and simple color change? SASS has a set of color operations that do nothing but eliminate the need to reach for the nearest color picker.

By implementing a preprocessor, you have the opportunity to concentrate directly on writing styles. Arithmetic responsive design works directly inside the style file, without switching to the calculator. Compass can take care of sprites for you. Separating styles into modular files and then combining them without impacting performance is seamless.

The main idea is that: these languages ​​allow you to focus on solving problems, instead of being distracted by tools and context switching.

Painless compilation

The main barrier to starting using CSS It's not usually a lack of understanding of whether it's good or bad for preprocessors - people are intimidated by the idea of ​​installing a package using the command line or the prospect of customization watch expressions. Fortunately, all these problems can be circumvented if suddenly the terminal is not your strong point.

Right in the browser

Not quite sure? Take a look at these browser implementations of preprocessors.

If we consider preprocessors together with CSS, we get a clearer picture than considering the concept of a preprocessor separately.

Definition

CSS preprocessor (from the English CSS preprocessor) is an add-on to CSS that adds previously unavailable capabilities to CSS using new syntactic constructs.

The main task of the preprocessor is to provide convenient syntactic structures for the developer to simplify, and thereby speed up the development and support of styles in projects.

CSS preprocessors convert code written using a preprocessor language into clean and valid CSS code.

With preprocessors, you can write code that targets:

  • Human readability
  • Structured and logical
  • Performance

And this is only a small part of what the preprocessor can give you. But don't get ahead of yourself.

Syntactic sugar

Before we look further at CSS preprocessors, let's update our vocabulary with a new concept: syntactic sugar.

Syntactic sugar (from the English syntactic sugar) are additions to the syntax of a programming language that do not introduce any significant changes or new features, but make the language more readable for humans.

Syntactic sugar introduces into the language alternative options records of constructions embedded in this language. Alternative recording options should be understood as shorter or more convenient constructions for humans, which will ultimately be converted by the preprocessor into the source language, without syntactic sugar.

If we try to apply this concept to CSS preprocessors, then, in the general case, it completely describes their essence. Let me remind you once again that the main task of preprocessors is to simplify and speed up development, but how else can this be done if you do not introduce alternative recording options?

What types of CSS preprocessors are there?

It's time to move on to more specific examples, namely to the CSS preprocessors themselves. At the time of writing, there are three popular preprocessors:

  • Sass (SCSS)
  • Stylus

And a few minor players for us:

  • Closure Stylesheets
  • CSS Crush

We will talk about the first three separately a little lower, but we won’t talk about the last two at all, due to their unpopularity. If desired, descriptions of these preprocessors can be easily found in a search engine.

What's the point of using preprocessors?

As I noted above, the main advantages are code readability, structuring and increased productivity.

There are also other reasons to start using a preprocessor today. I want to draw attention to this, since developers in the past, and many even now, refuse to use preprocessors, finding them complex, incomprehensible and unnecessary.

CSS is hard

Standard CSS is difficult. The non-nesting syntax that CSS preprocessors offer is simply hard to read. In addition, you need to remember the parent name when nesting. The lack of normal variables and "functions" makes CSS code messy and narrow-minded.

Available documentation

Gone are the days when documentation from preprocessors was available only to people “in the know.” Now anyone can as soon as possible master any of the preprocessors, and with minimal costs strength

Ease of use

Using preprocessors is easier than before, and much easier. To do this, you just need to install a program that will monitor the files intended for the preprocessor, and when they change, will compile the contents of these files into pure CSS code.

For more advanced users there are special project builders. Don't think that just because you're using a preprocessor program rather than a project builder that you're not cool enough. In fact, such faucets offer full control and advanced settings, but do not make you a Jedi.

Code structure and consistency

The most popular feature offered by any CSS preprocessor is the ability to nest selectors within each other. I won’t give an example now, since a corresponding part of the book will be written about Less’s capabilities, including nesting. At this point, all you should know is that when using preprocessors, you can nest one selector inside another, and another inside another, resulting in something similar to the table of contents of a book:

1. Parent selector 1.1. Nested selector 1.2. Nested selector 1.2.1. Nested selector 1.3. Nested selector

Of course, in real life selectors cannot begin with numbers, however, to draw a parallel between nesting and table of contents, I think such an omission is appropriate here.

Impurities

To put it very briefly, using mixins (from the English Mixins), you can make the code reusable. This helps to avoid helper classes in the markup or duplication of properties from selector to selector.

Modularity

Another bonus that would persuade me to start using a CSS preprocessor right now would be the ability to nest files within files, that is, in other words, to concatenate files in a given sequence. Yes, this can be arranged on pure CSS, but coupled with other features it turns out to be a very powerful tool.

At the same time, we get the opportunity to share modules (mixin libraries) that we created for our needs and found useful for other people. It turns out that any developer can download your library and use it for their own purposes, calling the mixins you wrote as needed.

Why not wait for CSS to evolve?

The development of CSS is taking very small and uncertain steps, as the W3C prioritizes the speed of CSS response (performance). On the one hand, this is correct and very important, but on the other hand, it is a lack of convenience for developers.

As an example, I’ll use one of the CSS4 specifications, which was introduced under pressure from developers - the parent selector. Such a long path from the idea to the decision was due to the fact that the W3C considered such a selector to be slow and its further use on sites would lead to wild slowdowns. Of course, we are talking about the widespread use of this selector, and not about isolated cases.

So don’t expect revolutions and changes in the near future that could overshadow the functionality and capabilities of CSS preprocessors.

Types of preprocessors

Of course, as in any other area, there is always competition, and in the preprocessor market there are now three main, warring camps:

  • Sass (SCSS)
  • Stylus

I call them hostile, because each adherent of one of the preprocessors considers it his duty to throw impurities at representatives of other, let’s say, faiths. This hostility is especially common among amateurs. Sass preprocessor, which is considered the oldest and most powerful of all three preprocessors.

For the sake of completeness, I want to give a brief overview of each preprocessor:

Less

Actually, the hero of this book. The most popular preprocessor at the time of writing. Founded in 2009 by Alexis Sellier and written in JavaScript (originally written in Ruby, but Alexis made the right move at the right time). Has everything basic capabilities preprocessors and even more, but does not have conditional structures and loops in the usual sense for us. The main advantage is its simplicity, almost standard for CSS syntax and the ability to expand functionality through a plugin system.

Sass (SCSS)

The most powerful of the CSS preprocessors. Has a fairly large developer community. Founded in 2007 as a module for HAML and written in Ruby (there is a port to C++). It has a much larger range of capabilities compared to Less. The capabilities of the preprocessor itself are expanded by the multifunctional Compass library, which allows you to go beyond CSS framework and work, for example, with sprites in automatic mode.

Has two syntaxes:

  • Sass (Syntactically Awesome Style Sheets) is a simplified CSS syntax that is identity-based. Considered obsolete.
  • SCSS (Sassy CSS) - based on standard CSS syntax.
Stylus

The youngest, but at the same time the most promising CSS preprocessor. Founded in 2010 by a well-known personality in our circles, TJ Holowaychuk. They say this is the most convenient and extensible preprocessor, and it is also more flexible than Sass. Written in JavaScript. Supports a lot of syntax options from CSS-like to simplified (missing: , ; , () and some parentheses).