CSS organization and conventions style guide

Introduction

All CSS rules are organized with small component files, which then are bundled into one CSS file per application. The Prototype project showcases most of the predefined and reusable view components.

Below documentation describes how to configure markup and styles of eRegistrations system with existing modules, and also describes style guide rules up to which HTML and CSS modules were developed, and up to which future extensions or system specific components should be developed.

CSS folders and files organization

All CSS is written and maintained in form of small modules, which then is bundled into browser ready files for configured applications.

General filename conventions

All names of CSS files must be lowercase with tokens separated with dashes. Good: foo-bar.css, Bad: fooBar.css

Location of prototype CSS modules

All generic CSS modules are placed in /css folder of eRegistrations project.

Base modules

Base foundation style files, can be found directly in /css folder:

  • base.css - Reset and base system wide styles
  • form.css - Styles related to form controls. It also contains all needed styles for form interfaces as generated by dbjs dom bindings
  • table.css - Base styles for tables
  • print-base.css - Reset and base styles for print views

Components

All other styles are organized as components, and can be found in /css/components folder.

Some of the components are documented in below part of this documentation. For those not documented, their purpose with styles and markup should be self explanatory.

Legacy degradation modules

There’s also /css/legacy folder which contains all eventual degradation rules which apply only to legacy browsers (ones that are served with static version of pages and not single page application program). It applies to IE10 and lower, IE mobile, and some very old versions of other engines.

Idea behind degradation rules: e.g. if there’s a component styled normally with flexbox, that is not supported in older IE engines. Then in legacy folder we may create corresponding component file (it’s name and location must exactly reflect location within /css folder) that provides alternative fixed rules for this component, so given part of interface remain functional and accessible in outdated engine as well.

Location of system specific CSS modules

They should be placed in /css folder of project.

What should land here is usually theme styles that apply specific system design, and eventual system specific components.

Same here, any eventual legacy degradation rules should be placed in corresponding files within /css/legacy folder.

CSS modules bundle configuration

Application modules bundle

For any application within eRegistrations system (where application is e.g. user, business-process-submitted) one major CSS bundle is created that includes css code for all used components.

Content of a bundle is configured per application, and takes place in css.index file placed in client folder of application

In index all files that should be concatenated into result bundle should be listed in desired order.

Creation of index file, is all what needs to be done for bundle to be generated automatically by the framework.

Exactly same way css index should be configured for print pages. In this case index is named css-print.index.

Legacy modules bundle

There’s no additional work needed to assure that legacy degradation rules are loaded for legacy engines. Bundle is generated automatically on basis of main css.index and CSS bundle file is linked automatically in html via static pages generator.

However, what’s important, there’s no special legacy handling configured for print views. Those views resemble very simple layout structures and should be styled by default as accessible also in old engines.

CSS style guide

No ID’s in selectors

Id’s specificity weight is very high therefore we decided not to rely on them. If id’s appear in markup their usage is reserved strictly for JS needs.

Class naming conventions

All introduced class names must be lowercase, with tokens separated with dashes. Good: foo-bar, Bad: fooBar, foo_bar

When deciding on new class names we take functional semantic approach, and not representational. e.g.

  • Good sidebar, Bad: column-2.
  • Good error-message, Bad: red-box

Whenever you’ll introduce new class names, it’ll be either cause of new component is introduced, or you customize existing component with additional class. Technically there should be no other case, if you think you approached one, please consult with other colleagues first.

When classifying components we follow some BEM conventions. While we do not follow it’s sophisticated class naming rules, we keep to the idea that all dependent sub component/state classes should be prefixed with main component name, and just by this single class referred further in CSS selectors.

e.g. we have steps menu component that’s displayed in user interface which is visible after user registers to the system. It is named: user-steps-menu, it becomes both, name of the class for the component and also the name of a CSS file which contains related rules.

Internally all sub component/state classes, are prefixed with users-steps-menu, e.g. users-steps-menu-wrapper, users-steps-menu-start-step. Same logic should be maintained when updating or introducing new components.

Minimal selectors

Selectors introduced in CSS files, must remain as minimal as possible.

Graceful degradation, no old school hacks

In first place we style for modern engines, no look backs.

It’s not allowed to use float hacks to compose layout. Instead rely on flexbox or display: inline-block, or display: table. If you need rounded corners, rely strictly on border-radius, for gradients, use dedicated background properties. All of this features are already supported in all latest versions of major engines.

Handling older engines

We want to support old engines as far as IE8. Still, it’s only about making the application usable and fully functional, we do not strive to make it look exactly same as on modern engine.

To introduce necessary tweaks to old engines, we configured mechanism that allows to add degradation rules for components for which regular styles break layout in old engines. See Legacy degradation modules and Legacy modules bundle sections to see how to apply them. Over there it’s allowed to rely on float if needed. Still it needs to be minimal, and should be strictly about addressing layout or significant usability breakages. Do not try to try to make round corners for IE, or introduce other not natively supported sugar for this engines.

Other important rules guarded with lint utility

CSS code is validated with CSS lint utility. It checks the code against most of pre-configured rules and some white-space rules added by us.

We had reasons to opt out of some rules, list of it can be found in project .lint configuration.

Every eRegistrations system should have CSS lint tasks configured, and eventual CSS lint configuration added to .lint files.

Dealing with vendor prefixes

There’s the Autoprefixer utility configured with the bundler. So it’s fine to use only standard names in CSS files, they will be automatically resolved to all needed vendor prefixes.

CSS Variables

CSS variables are used to address common colors or dimension settings that repeat across rules. They’re resolution is configured within a bundler with help of css-aid utility

Vertical Rhythm

All page layouts are composed with respect to vertical rhythm. More information on VR can be found in this article.

Base line height of our VR setup is 22px

In development we confirm VR with help of browser extensions, e.g. GridFox on Firefox or PixelPerfect for Chrome (for this use grid-22.png image)

It’s allowed to introduce small exceptions to the rule (e.g. show input hint closer to input box), but overall vertical rhythm of a page must remain maintained.

It’s also OK, to ignore eventual browser bugs which cause small deviations from vertical rhythm. Still for Google Chrome and Mozilla Firefox browsers we strive for perfection.

Responsiveness

At this point eRegistrations application layout is configured for both desktop and mobile views. Switch to mobile version occurs when screen resolution is less than 640px.

Styles specific to mobile view, can be applied via media-queries.

Minimum mobile resolution is set to 320px.

Control of responsive display is mostly done by changing flex-wrap property set to wrap in mobile view.

Example can be found here.

Browsers we support

We support all major engines (Chrome, Firefox, Safari, IE, Opera) on both desktop and mobile in their latest versions. Via additional legacy degradation styles we maintain application as fully usable and functional for all engines which can’t run application in SPA mode. Our support goes lowest to IE8 browser.

Components

Below is list of notes for some components for which we felt some additional documentation is needed. For all others markup and styles should be self explanatory.

Responsive tables

Responsive table flips its header to be first column for every row of table. From the code perspective, this can be achieved simply by adding property responsive: true on a table.

Example can be found here

Font icons

Font Awesome is used in eRegistrations for icons. Only icons that we actually use are configured. Any new icons need to be added to icons file: css/components/fa.css.

Adding new icon can be made by selecting new icon from this list and adding class for this font in css/components/fa.css

Example - adding automobile icon requires adding its class and :before pseudo-element:

.fa-automobile {
	width: 1.2em;
}
.fa-automobile:before {
	content: "\f1b9";
}

Then in templates a element need to be added:

span({ class: 'fa fa-automobile' }, "Car")

“Car” text will not be shown when CSS is applied.

Tooltips (optional hints)

Tooltips are small, black, pop-up windows that are displayed on hover over significant element. Our component is developed on top of vendor library - hint.css.

Any element which needs to have a tooltip has to be given hint-optional class. To position hint, at least one of the position classes need to be added:

hint-optional-top,
hint-optional-bottom,
hint-optional-left,
hint-optional-right

The tooltip text has to be given using the data-hint attribute on that element.

Example can be found here.

span({ class: 'hint-optional hint-optional-left', 
		'data-hint': "Lorem ipsum dolor sit amet" },
	"Lorem ipsum"
	);

Free-form text

It’s the component we use, where we inject multi-paragraph i18n messages with markdown support.

It provides sensible styles to lists, paragraphs etc. for such scenario.

Example can be found here.

Disabler

Disabler is a component, that can cover all other components under partially transparent background, and make all of them not clickable

Disabler requires a wrapper component, containing all elements that should be disabled. This wrapper component needs to have disabler-range class.

Disabler requires empty div with disabler class, as first line last child element.

For turning on disabler, a disabler-active class needs to be added to disabler-range component.

div({ class: 'disabler-range' },
	"Lorem ipsum to be disabled",
	
	div({ class: 'disabler' })
);