
CSS development on github
From a translator: This
article was written on behalf of Mark Otto , one of the leading maintainers of the popular front-end framework Twitter Bootstrap, now a CSS developer on GitHub .
I was always interested in the process of developing different applications, especially their style guides and their approach to CSS development. Given my penchant for sometimes meaningless details in CSS development, I decided to write a little about the CSS development process on GitHub.
An overview of the current state of the CSS code shows:
As stated above, we use SCSS. This choice was made long before my arrival and I have nothing against it (despite the fact that Bootstrap is currently being developed on LESS). Our SCSS files are compiled by Ruby on Rails with some help from Sprockets to include files. More on this later.
What about LESS, Stylus, or ...? I don’t think GitHub once planned to switch to LESS, but I can’t say that. Now we also, most likely, will not switch to development using LESS, because We do not see obvious advantages.
Why are you using a preprocessor at all?Our internal framework includes a relatively small set of variables (such as mixing fonts or primary colors) and mixins (most often for properties with vendor prefixes), which makes code development faster and easier.
At the moment we are not using Autoprefixer, but, in fact, we should, because in this case, almost all of our mixins will not be needed. I hope that we will realize this soon.
Also at the moment we are not using source maps , but that will change soon. (If you did not know, source maps allow you to see in the Inspector'e of the browser from which source SCSS file this set of styles was compiled, instead of compiled and compressed CSS. They are cool.)
In addition to this, we use very few SCSS features. In our case, SCSS functionality comes down to using variables, mixins, color functions ( darken, lighten , etc), mathematical functions, and inheritance.
Currently, two popular approaches to CSS architecture are BEM and OOCSS . We are leaning towards OOCSS, but we do not have a holistic and global approach. We are trying to develop new elements with a vague approach combining the properties of these two approaches, but which has the following basic features:
I will write more about my preferred CSS architecture in another post. Now, the text above summarizes the GitHub approach, which, of course, is not perfect, but does a good job of what is required of it.
We started using our SCSS syntax check a few weeks ago. We had our own conditional conventions regarding the code style, but the style and formatting of each developer was somewhat unique. Now, each CI build includes a basic SCSS linting and the file was not released into the build if:
All in all, these few rules keep our code pretty clean. They do not include discrepancies in the style of commenting or the general architecture, but this team should be composing for themselves with the help of documentation. This is something where everyone can correct and supplement something.
GitHub has a set of two CSS files, github and github2 . The file was split several years ago to solve the problem of a limit of 4095 selectors per file . This limit applies to versions of IE 9 and earlier, as GitHub requires IE9 support, our CSS separation approach will remain valid for a long time to come. Because today GitHub has about 7000 selectors in these two files. Compare these numbers with data from other sites:
These numbers were generated by cssstats.com . This is a very cool little utility that looks at your styles from the side that most developers, including me, usually don’t look at their files. Also inside GitHub we use charts and usually use it for our own needs.
GitHub's CSS and JavaScript are included through Sprockets and require . We develop our CSS code using divided subdirectories inside the app / assets / shylesheet s folder . Here's what it looks like:
We include our dependencies (Primer is our internal framework) and after that we include all SCSS files of the folder in the order in which Sprockets decides to include them (it seems to me alphabetically). The ease with which we can bind our styles (simply with the require_directory . Command ) is striking, but there are also drawbacks to this.
The order in which styles are applied (and, accordingly, the order in which files are included) is important. In fact, this should not be so, but in every design system there are rules and a basic hierarchy of styles. With the Sprockets approach, we sometimes run into specific issues. This happens because new files can be added to either of the two CSS files at any time. Depending on the name of the files, they appear in different places in the compiled CSS.
In addition, the use of Sprockets implies that your SCSS files do not have direct and automatic access to your global variables and mixins. This leads to the fact that you must include them (via @ import ) every time at the top of every SCSS file that accesses a variable or mixin.
Inside GitHub, we use many graphs to track how the site and API are doing. We also track several interesting front-end features. For example, here is a graph illustrating the size of our two CSS files in the last 3 months:

Also, here is a graph of the number of selectors in CSS files in the last 3 months on our blob pages . Obviously, we still have a lot of work to reduce the number of tag selectors.

Due to the fact that we constantly add updated CSS files and add dozens of them every day, we constantly knock down the caches of our rather large CSS files. We have done little to optimize file sizes or reduce cache failures, but we are starting to look more closely at this direction. It would be very cool to have a core file, which, hopefully, will change very rarely and a secondary file that we would change more often.
Opening this topic on Twitter, we had (not sure if they have it now) 2 files, core and more . The core file contained the styles necessary to make the time elapsed before the first tweet as small as possible. Everything else was in the file more. Knowing GitHub’s love for quick changes (nothing is ported here unless it was ported quickly), we will turn our attention to this approach. Now our two files are separated arbitrarily.
In general, optimizing selector performance does not bother us much . We are aware of bad approaches: excessive investments, IDs, elements, etc., but we are not trying to reoptimize. The one exception was the diff page . Due to the too much markup needed to render the diff page, we avoided attribute selectors like [class ^ = ”octicon”] . When used too often, these attribute selectors can crash (and crash) browsers.

Speaking about it, we are doing quite a good job for ourselves, but we are also working on improvements. We have a publicly accessible CSS style guide and all of our general CSS guidelines live there, as well as examples of most components. It is built on KSS , a style guide generator.
It's not perfect, but it allows developers to find and use components quickly. This is also a great way to show our new development process to new developers in order to bring them to the usual development speed faster (as I did when I joined about two years ago).

I hinted at this before, but for those who are not up to date, Primer p is our internal framework for common styles and components inside our public and internal applications. It includes:
We use it on GitHub.com, Gist and several internal applications.
Most Primer components are documented in our style guide (navigation, tooltips, etc.) Despite this, we recently started updating and improving Primer, so many components are changing now.
For those who would like to ask, I would very much like to publicize parts of Primer, but little will change in this direction in the near future. Still, I have hope.
We have a decent piece of legacy code that includes CSS. Unlike a public open source project that has strict version rules, we get rid of unnecessary code regularly if these solutions suit us. Finding things to remove is done in two ways:
The general refactoring process is probably not unique to GitHub. We find things that should be removed, delete them, discuss them publicly, let the CSS development team know about it and port them as quickly as possible. Any team member can delete the code. We have many developers who directly add something new to GitHub, but we also have a lot of nerds analyzing what we can remove.
article was written on behalf of Mark Otto , one of the leading maintainers of the popular front-end framework Twitter Bootstrap, now a CSS developer on GitHub .
I was always interested in the process of developing different applications, especially their style guides and their approach to CSS development. Given my penchant for sometimes meaningless details in CSS development, I decided to write a little about the CSS development process on GitHub.
a brief description of
An overview of the current state of the CSS code shows:
- Using SCSS as a preprocessor;
- We have over 100 separate source stylesheets that we compile before being released into production;
- Compiled CSS is divided into 2 files to avoid the limit on the number of selectors in versions IE <10;
- These two files have a total weight of 90KB;
- We do not adhere to any specific approach in the CSS architecture;
- We use pixels as the unit of measure, although sometimes we also use em;
- We use Normalize.css and mix our own discard styles.
Preprocessor
As stated above, we use SCSS. This choice was made long before my arrival and I have nothing against it (despite the fact that Bootstrap is currently being developed on LESS). Our SCSS files are compiled by Ruby on Rails with some help from Sprockets to include files. More on this later.
What about LESS, Stylus, or ...? I don’t think GitHub once planned to switch to LESS, but I can’t say that. Now we also, most likely, will not switch to development using LESS, because We do not see obvious advantages.
Why are you using a preprocessor at all?Our internal framework includes a relatively small set of variables (such as mixing fonts or primary colors) and mixins (most often for properties with vendor prefixes), which makes code development faster and easier.
At the moment we are not using Autoprefixer, but, in fact, we should, because in this case, almost all of our mixins will not be needed. I hope that we will realize this soon.
Also at the moment we are not using source maps , but that will change soon. (If you did not know, source maps allow you to see in the Inspector'e of the browser from which source SCSS file this set of styles was compiled, instead of compiled and compressed CSS. They are cool.)
In addition to this, we use very few SCSS features. In our case, SCSS functionality comes down to using variables, mixins, color functions ( darken, lighten , etc), mathematical functions, and inheritance.
Architecture
Currently, two popular approaches to CSS architecture are BEM and OOCSS . We are leaning towards OOCSS, but we do not have a holistic and global approach. We are trying to develop new elements with a vague approach combining the properties of these two approaches, but which has the following basic features:
- Preference for classes than anything else (IDs, tags) in selectors;
- Evasion of unnecessary inheritance;
- Use of (single) hyphens in class names;
- We try to give the shortest possible names to classes, but without creating confusion and confusion.
I will write more about my preferred CSS architecture in another post. Now, the text above summarizes the GitHub approach, which, of course, is not perfect, but does a good job of what is required of it.
Syntax Check (linting)
We started using our SCSS syntax check a few weeks ago. We had our own conditional conventions regarding the code style, but the style and formatting of each developer was somewhat unique. Now, each CI build includes a basic SCSS linting and the file was not released into the build if:
- Your class is in CSS, but it is not found anywhere in the app / views template folder ;
- You use the same selector several times (since they almost always have to be combined);
- The general formatting rules (inheritance limits, indent between the rules, no spaces after : etc.) are violated.
All in all, these few rules keep our code pretty clean. They do not include discrepancies in the style of commenting or the general architecture, but this team should be composing for themselves with the help of documentation. This is something where everyone can correct and supplement something.
Two CSS files
GitHub has a set of two CSS files, github and github2 . The file was split several years ago to solve the problem of a limit of 4095 selectors per file . This limit applies to versions of IE 9 and earlier, as GitHub requires IE9 support, our CSS separation approach will remain valid for a long time to come. Because today GitHub has about 7000 selectors in these two files. Compare these numbers with data from other sites:
- Bootstrap v3.2.0 has a little less than 1900 selectors;
- Twitter has just under 8900 selectors;
- NY Times - about 2100 selectors;
- SoundCloud (new version) - about 1100.
These numbers were generated by cssstats.com . This is a very cool little utility that looks at your styles from the side that most developers, including me, usually don’t look at their files. Also inside GitHub we use charts and usually use it for our own needs.
Inclusions via Sprockets
GitHub's CSS and JavaScript are included through Sprockets and require . We develop our CSS code using divided subdirectories inside the app / assets / shylesheet s folder . Here's what it looks like:
/*
= require primer/basecoat/normalize
= require primer/basecoat/base
= require primer/basecoat/forms
= require primer/basecoat/type
= require primer/basecoat/utility
= require_directory ./shared
= require_directory ./_plugins
= require_directory ./graphs
= require primer-user-content/components/markdown
= require primer-user-content/components/syntax-pygments
= require primer/components/buttons
= require primer/components/navigation
= require primer/components/behavior
= require primer/components/alerts
= require primer/components/tooltips
= require primer/components/counter
= require primer-select-menu
= require octicons
= require_directory .
*/
We include our dependencies (Primer is our internal framework) and after that we include all SCSS files of the folder in the order in which Sprockets decides to include them (it seems to me alphabetically). The ease with which we can bind our styles (simply with the require_directory . Command ) is striking, but there are also drawbacks to this.
The order in which styles are applied (and, accordingly, the order in which files are included) is important. In fact, this should not be so, but in every design system there are rules and a basic hierarchy of styles. With the Sprockets approach, we sometimes run into specific issues. This happens because new files can be added to either of the two CSS files at any time. Depending on the name of the files, they appear in different places in the compiled CSS.
In addition, the use of Sprockets implies that your SCSS files do not have direct and automatic access to your global variables and mixins. This leads to the fact that you must include them (via @ import ) every time at the top of every SCSS file that accesses a variable or mixin.
Performance
Inside GitHub, we use many graphs to track how the site and API are doing. We also track several interesting front-end features. For example, here is a graph illustrating the size of our two CSS files in the last 3 months:

Also, here is a graph of the number of selectors in CSS files in the last 3 months on our blob pages . Obviously, we still have a lot of work to reduce the number of tag selectors.

Due to the fact that we constantly add updated CSS files and add dozens of them every day, we constantly knock down the caches of our rather large CSS files. We have done little to optimize file sizes or reduce cache failures, but we are starting to look more closely at this direction. It would be very cool to have a core file, which, hopefully, will change very rarely and a secondary file that we would change more often.
Opening this topic on Twitter, we had (not sure if they have it now) 2 files, core and more . The core file contained the styles necessary to make the time elapsed before the first tweet as small as possible. Everything else was in the file more. Knowing GitHub’s love for quick changes (nothing is ported here unless it was ported quickly), we will turn our attention to this approach. Now our two files are separated arbitrarily.
In general, optimizing selector performance does not bother us much . We are aware of bad approaches: excessive investments, IDs, elements, etc., but we are not trying to reoptimize. The one exception was the diff page . Due to the too much markup needed to render the diff page, we avoided attribute selectors like [class ^ = ”octicon”] . When used too often, these attribute selectors can crash (and crash) browsers.
Documentation

Speaking about it, we are doing quite a good job for ourselves, but we are also working on improvements. We have a publicly accessible CSS style guide and all of our general CSS guidelines live there, as well as examples of most components. It is built on KSS , a style guide generator.
It's not perfect, but it allows developers to find and use components quickly. This is also a great way to show our new development process to new developers in order to bring them to the usual development speed faster (as I did when I joined about two years ago).
Primer

I hinted at this before, but for those who are not up to date, Primer p is our internal framework for common styles and components inside our public and internal applications. It includes:
- Normalize
- Global styles for box-sizing , typography, links, etc .;
- Navigation
- Forms
- Mesh;
- Markup styles;
- Special select menu.
We use it on GitHub.com, Gist and several internal applications.
Most Primer components are documented in our style guide (navigation, tooltips, etc.) Despite this, we recently started updating and improving Primer, so many components are changing now.
For those who would like to ask, I would very much like to publicize parts of Primer, but little will change in this direction in the near future. Still, I have hope.
Code Reactor
We have a decent piece of legacy code that includes CSS. Unlike a public open source project that has strict version rules, we get rid of unnecessary code regularly if these solutions suit us. Finding things to remove is done in two ways:
- Manual search for things that look similar, but actually have different HTML and CSS code, and the subsequent combination;
- Running a script that looks for a class in our CSS and checks to see if it is in our view files.
The general refactoring process is probably not unique to GitHub. We find things that should be removed, delete them, discuss them publicly, let the CSS development team know about it and port them as quickly as possible. Any team member can delete the code. We have many developers who directly add something new to GitHub, but we also have a lot of nerds analyzing what we can remove.