Requests for comment/Grid system

This document proposes to include a Grid system in MediaWiki to simplify the creation of user interfaces and make them ready for multiple screen sizes.

What is a grid system and why is it needed?
A grid system defines a set of guides that help in the layout of visual elements. In this way the available space is divided in several columns and rows where content can be placed. For example, if we use a 12-column grid we can define a sidebar to occupy two columns.

Grids provide consistency in the layout. They make it easy to align elements in order to achieve cleaner designs. Grid systems reduces the need for custom layout code on a per-element basis that becomes hard to adjust when new elements are added or the layout needs to be modified (especially if those modifications happen dynamically).

The high diversity of screen sizes (from small mobile devices to big TV screens) makes it hard to appropriately use the available space for each screen size. Responsive design techniques use a grid system to indicate how the layout changes from screen to screen. For example, the 2-column sidebar menu displayed in a desktop computer can become a full-width menu on a mobile device.

The above scenario can be supported with a grid system in the following way:

Adding a grid system to MediaWiki will provide two main benefits:
 * Consistency across different extensions. Making the UI code easier to develop, understand and modify.
 * Optimise the user experience for different screen sizes. Making it possible to indicate how to adapt UIs to the available space with minimal replication.

What kind of grid system?
There are many kinds of grids with different properties. Considering the MediaWiki context, the most relevant properties considered for a grid system are: Optional, Nestable, Proportional, Responsive and Semantic. Most of these aspects are similar to the ideas proposed in this article.

The proposed grid system uses style classes following the breakpoint-proportion format (e.g., desk-two-thirds, palm-one-half) to indicate the layout of elements in a specific screen size.

Optional
Using a grid is great but you should not be forced to do so. Developers should be able to decide whether to use the grid system for any part of their user interfaces, or not to use it at all. CSS classes should be properly scoped to avoid affecting/breaking the layout of existing non-grid-based components.

Nestable
Defining a grid inside another grid provides the flexibility needed for the composition of UI elements. For example, it should be possible to add a grid-based component inside both a page that uses a grid-based layout and a page that does not.

Proportional
The use of proportions is preferred to using a fixed number of columns. "Half the available space" (proportion), is equivalent to "six columns" on a 12-column grid (fixed columns). However, for the "six columns" you need to know the total number of columns available to understand its dimensions.

This becomes a bigger problem when targeting multiple screen sizes. Fixed-column grid systems use a different number of columns are used for each breakpoint (e.g., 12 on desktop and 4 for mobile devices). In his context, it becomes even harder to figure what "two columns" mean for an element's layout on a fixed column responsive grid.

Responsive
Responsive grid systems define a set of screen sizes or breakpoints (by means of CSS media queries) so that you could indicate that a half-width element becomes a full-width element for small screens. Considering the increasing number of devices it is desirable that:
 * Breakpoints are defined in a device-independent manner. One possible solution is to use general form-factors such as palm, lap, portable (palm and desk), and desk. Another option is to use abstract sizes such as S, M, L, XL.
 * Default breakpoint. If no breakpoint is provided (e.g., "on-half"), the layout is applied to all screen sizes unless another breakpoint-specific class is added for the element.
 * New breakpoints can be easily added. At some point you will want to provide support for new screen sizes (e.g., watches, TV screens) and you should be able to add new breakpoints to support them.
 * Fluid columns between breakpoints. Columns should adapt to the available space.

Semantic
In the most basic form, a grid system is implemented by a set of CSS rules. This means that classes such as "palm-one-half" are added to HTML elements to control their layout. Adding layout-related information to the markup can be considered a problem if you want to include just content.

If the grid system is defined by means of a CSS preprocessor, developers can reuse the provided classes when creating their own. For example a sidebar class can be defined in LESS based on the classes from the grid system:

In this way, the sidebar at the HTML document can just use the "sidebar" class without any additional layout-related class.

For this to be possible, a CSS preprocessor as proposed in LESS RFC should be available.

Implementation
The grid system will be supported as a set of LESS mixins and variables. This means that, the grid classes will not be exposed to the generated CSS. That will (a) lead to smaller and more semantic CSS and HTML, (b) reduced dependency with the grid concepts used and their implementation, and (c) avoid grid classes to be used out of their intended target (UI as opposed to user-generated content).

An example implementation is available.

A patchset was submitted to Gerrit.

Variables

 * Grid gutter. The @grid-gutter variable defines the default separation between the grid elements (it can be overridden for specific elements).
 * Breakpoints. A variable is defined for each screen size we want to support. Examples of the current initial ones is provided below:

@palm: ~"only screen and (max-width: 480px)"; @lap: ~"only screen and (min-width: 481px) and (max-width: 1023px)"; @portable: ~"only screen and (max-width: 1023px)"; @desk: ~"only screen and (min-width: 1024px)";

Mixins
The main mixins provide are:
 * mw-ui-grid. Defines the outer container for a grid.
 * mw-ui-one-whole, mw-ui-one-half, mw-ui-one-third, mw-ui-two-thirds ... mw-ui-eleven-twelfths. Mixins to define the proportion of an item inside a grid.
 * A responsive version of the proportional mixins above, where you can indicate to which screen-size they apply. For example, mw-ui-one-third(@palm).

Additional mixins that may be useful:
 * mw-ui-item. Sets basic properties for a grid item.
 * mw-ui-gutter. Defines the gutter (separation) for items in a grid.
 * mw-ui-hidden. Control visibility depending on the viewport.

Example of use
When styling an element in LESS we can define how layout and other properties changes according to the breakpoints defined.

Other options considered
Several implementations exist of grid systems that are based on similar ideas as the one described below and may constitute a great foundation to define the MediaWiki grid based on them. Further technical assessments are required to make the adequate implementation decisions to support the grid system described in this document in the best way considering cross-browser issues among other implications.
 * csswizardry-grids. This system has been an inspiration for the concepts defined above so it supports them as described. Grid columns are based on inline-block elements which become problematic when dealing with white space. They either require a markup free of white spaces between blocks, or the use of a hack to remove the white spaces whose browser-compatibility is not clear.
 * proportional-grids. Grid system based on float elements, which follow some of the principles described above. The use of float elements provides less flexibility in layout compared to inline-block elements but avoids the problem with white spaces of csswizard-grids.
 * (experimental) agora-grid. Based on the proportional-grids system, I made an experimental adaptation to support the proposed concepts using LESS CSS preprocessors.
 * Basing the grid system on CSS3 Grid layout will be a logical step, but at the moment it is just a draft with little browser support.
 * VisualEditor has a class called ve.ui.GridLayout that is used in the template dialog and the page settings dialog. It provides a two-dimensional, proportional grid and is nestable.
 * Guidelines for responsive design following similar approach.
 * The 2015 US Federal Government Web design standards followed a very similar approach.

MediaWiki extensions that already use grid system

 * Extension:Translate and Extension:UniversalLanguageSelector uses a modified version of Foundation grid.
 * OOjs UI (used by Extension:VisualEditor and others) implements a own grid class via the OO.ui.GridLayout class.