From 63058f2e11948d852947159086131d107dae369b Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 2 Mar 2017 17:35:38 -0500 Subject: [PATCH 01/98] Update coding_guidelines.rst --- development/development/coding_guidelines.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/development/development/coding_guidelines.rst b/development/development/coding_guidelines.rst index 75d131a7..391453f5 100644 --- a/development/development/coding_guidelines.rst +++ b/development/development/coding_guidelines.rst @@ -18,3 +18,14 @@ We use JSHint and JSCS for checking the quality of the JavaScript—JSHint for linting, and JSCS for ensuring consistent code. There is a .jshintrc and a .jscs file in the root of the project, and your editor probably has a plugin available which will show you when you violate these standards. + +CSS & SCSS Linting +------------------ + +We use `stylelint ` for checking the quality, linting, +and ensuring consistent CSS code standards. There is a .stylelintrc +file in the root of the project, and your editor probably has a plugin available +which will show you when you violate these standards. + +We employ a set of standards loosely based on the following widely used +`CSS Guidelines ` From fe44762a9c999e8ef93d294eea9d0b15b155b5ac Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Tue, 28 Mar 2017 16:08:03 -0400 Subject: [PATCH 02/98] fix links --- development/development/coding_guidelines.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/development/development/coding_guidelines.rst b/development/development/coding_guidelines.rst index 391453f5..b8b5e2a2 100644 --- a/development/development/coding_guidelines.rst +++ b/development/development/coding_guidelines.rst @@ -22,10 +22,10 @@ available which will show you when you violate these standards. CSS & SCSS Linting ------------------ -We use `stylelint ` for checking the quality, linting, +We use `stylelint `_ for checking the quality, linting, and ensuring consistent CSS code standards. There is a .stylelintrc file in the root of the project, and your editor probably has a plugin available which will show you when you violate these standards. We employ a set of standards loosely based on the following widely used -`CSS Guidelines ` +`CSS Guidelines `_ From 39761b684c7716a04a707074fd4a3eda1db04c9f Mon Sep 17 00:00:00 2001 From: javiexin Date: Wed, 19 Jul 2017 14:31:41 +0200 Subject: [PATCH 03/98] [ticket/15274] Document parameters for custom functions Also, show example of compatibility with multi step process --- development/migrations/data_changes.rst | 71 +++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/development/migrations/data_changes.rst b/development/migrations/data_changes.rst index 8893121b..8450c152 100644 --- a/development/migrations/data_changes.rst +++ b/development/migrations/data_changes.rst @@ -179,6 +179,77 @@ Example return $value + $limit; } +Passing parameters to custom functions +-------------------------------------- + +.. note:: + + This functionalilty is only available from 3.2.2 onwards + +.. code-block:: php + + array('custom', array( + array(/* Callable function */), array(/* Parameters to the function */), + )), + +Example +------- + +Call a function within the migrations file named some_function, passing it some parameters + +.. code-block:: php + + array('custom', array( + array($this, 'some_function'), array('first param', 2) + )), + +.. note:: + + The function called must accept the specified parameters + +Example +------- + +Fully compatible with multi step process + +.. code-block:: php + + public function update_data() + { + return array( + array('custom', array( + array($this, 'some_function'), array(500) // The param is the limit + )), + ); + } + + // $value is the value returned on the previous call, and is always the last parameter + public function some_function($limit, $value) + { + $i = 0; + + // Select all topics, starting at $value, limit $limit + while ($topic = fetchrow) + { + $i++; + + // Do something + } + + if ($i < $limit) + { + // There are no more topics, we are done + return; + } + + // There are still more topics to query, return the next start value + return $value + $limit; + } + +.. note:: + + The function called must accept the specified parameters, plus the $value param as the last one + Examples ======== From d53948f3a2a23fdb4737690c4d32fcf225ab2b02 Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 20 Jul 2017 12:29:14 +0200 Subject: [PATCH 04/98] [ticket/15274] Document parameters for custom functions Fix typo and clarify multi-step compatibility --- development/migrations/data_changes.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/development/migrations/data_changes.rst b/development/migrations/data_changes.rst index 8450c152..fc3e4dbe 100644 --- a/development/migrations/data_changes.rst +++ b/development/migrations/data_changes.rst @@ -184,7 +184,7 @@ Passing parameters to custom functions .. note:: - This functionalilty is only available from 3.2.2 onwards + This functionality is only available from 3.2.2 onwards .. code-block:: php @@ -248,7 +248,8 @@ Fully compatible with multi step process .. note:: - The function called must accept the specified parameters, plus the $value param as the last one + To support the multi-step process, the function called must accept the explicit parameters, + plus an additional last parameter that will receive the receive the return of the previous step. Examples ======== From fc7b4c9e7c0496b0d9eeb1fa7835402dad6bad9c Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 20 Jul 2017 14:13:37 +0200 Subject: [PATCH 05/98] [ticket/15274] Document parameters for custom functions Fix another typo --- development/migrations/data_changes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/migrations/data_changes.rst b/development/migrations/data_changes.rst index fc3e4dbe..c4d1c0c8 100644 --- a/development/migrations/data_changes.rst +++ b/development/migrations/data_changes.rst @@ -249,7 +249,7 @@ Fully compatible with multi step process .. note:: To support the multi-step process, the function called must accept the explicit parameters, - plus an additional last parameter that will receive the receive the return of the previous step. + plus an additional last parameter that will receive the return of the previous step. Examples ======== From 675e60f56d64334b1e183b583eeac9490e7d5c69 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 7 Sep 2017 16:51:58 +0200 Subject: [PATCH 06/98] add stylelint config info --- development/development/phpstorm.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/development/development/phpstorm.rst b/development/development/phpstorm.rst index 1fe37067..271b3def 100644 --- a/development/development/phpstorm.rst +++ b/development/development/phpstorm.rst @@ -53,7 +53,7 @@ The general rule here is that braces always go on new lines. CSS, JavaScript, HTML, Twig ########################### -Tabs should be used (not spaces). All tab and indent sizes should be set to 4 spaces. +Tabs should be used (not spaces). All tab and indent sizes should be set to 4 spaces. Also be sure "Keep indents on empty lines" is NOT checked. JSON & YAML @@ -72,6 +72,8 @@ The default inspection settings should work just fine. However there are a coupl * phpBB uses fully qualified namespaces, so you can turn off this inspection warning **PHP > Code Style > Unnecessary fully qualified name**. * You may enable additional JavaScript inspections. Under **JavaScript > Code quality tools**, you can enable JSCS, JSHint, JSlint and/or ESLint. phpBB comes with configuration files for JSHint and JSCS. With these inspections enabled, you can use the configuration files provided by phpBB instead of PhpStorm's default settings. To do so, point PhpStorm to the custom configuration files under **Language & Frameworks > JavaScript > Code Quality Tools**. Point JSHint to `.jshintrc` and point JSCS to `.jscsrc`. +.. warning:: Stylelint is not bundled with PhpStorm. The Stylelint tool is run through NodeJS. To use Stylelint, make sure the NodeJS framework is downloaded and installed on your computer. Then you can follow these `Instructions `_. + .. warning:: JSCS is not bundled with PhpStorm. The JSCS tool is run through NodeJS. To use JSCS, make sure the NodeJS framework is downloaded and installed on your computer. Then you can install JSCS via the npm package manager and configure the JSCS options in PhpStorm to use the JSCS package. For more information review `PhpStorm's documentation `_. .. note:: phpBB uses jQuery. The Javascript inspections need to be made aware of jQuery to avoid any false warnings/errors. To do this, simply go to **Languages & Frameworks > JavaScript > Libraries** and enable jQuery. If jQuery is not in the list, you can use the "Download" button to download a copy of jQuery to PhpStorm. From c3aa17b89272e8cdc16ddb75445019699a9a1f70 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 7 Sep 2017 17:05:45 +0200 Subject: [PATCH 07/98] update link --- development/development/phpstorm.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/development/phpstorm.rst b/development/development/phpstorm.rst index 271b3def..a32a736e 100644 --- a/development/development/phpstorm.rst +++ b/development/development/phpstorm.rst @@ -72,7 +72,7 @@ The default inspection settings should work just fine. However there are a coupl * phpBB uses fully qualified namespaces, so you can turn off this inspection warning **PHP > Code Style > Unnecessary fully qualified name**. * You may enable additional JavaScript inspections. Under **JavaScript > Code quality tools**, you can enable JSCS, JSHint, JSlint and/or ESLint. phpBB comes with configuration files for JSHint and JSCS. With these inspections enabled, you can use the configuration files provided by phpBB instead of PhpStorm's default settings. To do so, point PhpStorm to the custom configuration files under **Language & Frameworks > JavaScript > Code Quality Tools**. Point JSHint to `.jshintrc` and point JSCS to `.jscsrc`. -.. warning:: Stylelint is not bundled with PhpStorm. The Stylelint tool is run through NodeJS. To use Stylelint, make sure the NodeJS framework is downloaded and installed on your computer. Then you can follow these `Instructions `_. +.. warning:: Stylelint is not bundled with PhpStorm. The Stylelint tool is run through NodeJS. To use Stylelint, make sure the NodeJS framework is downloaded and installed on your computer. Then you can follow these `Instructions `_. .. warning:: JSCS is not bundled with PhpStorm. The JSCS tool is run through NodeJS. To use JSCS, make sure the NodeJS framework is downloaded and installed on your computer. Then you can install JSCS via the npm package manager and configure the JSCS options in PhpStorm to use the JSCS package. For more information review `PhpStorm's documentation `_. From 4bf126b5aac19c11ec844348043ae47f3d7795c9 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 9 Sep 2017 15:31:03 +0200 Subject: [PATCH 08/98] Fix master version in sphinx config --- development/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/development/conf.py b/development/conf.py index fe8d8d70..99e8611d 100644 --- a/development/conf.py +++ b/development/conf.py @@ -57,9 +57,9 @@ # built documents. # # The short X.Y version. -version = '3.2' +version = 'master' # The full version, including alpha/beta/rc tags. -release = '3.2.x' +release = 'master' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From a05e6d8b3aaa59338fc878a97ce7c2364fddcf68 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 7 Sep 2017 16:48:47 +0200 Subject: [PATCH 09/98] add css guidelines --- development/development/css_guidelines.rst | 600 +++++++++++++++++++++ 1 file changed, 600 insertions(+) create mode 100644 development/development/css_guidelines.rst diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst new file mode 100644 index 00000000..44160ff3 --- /dev/null +++ b/development/development/css_guidelines.rst @@ -0,0 +1,600 @@ +Introduction +============ + +CSS is not a pretty language. While it is simple to learn and get started with, +it soon becomes problematic at any reasonable scale. There isn’t much we can do +to change how CSS works, but we can make changes to the way we author and +structure it. + +There are a variety of techniques we must employ in order to satisfy these +goals, and CSS Guidelines is a document of recommendations and approaches that +will help us to do so. + +The first part of this will deal with syntax, formatting and CSS anatomy, the +second part will deal with approach, mind frame and attitude toward writing and +architecting CSS. + + +Meaningful Whitespace +===================== + +Only one style should exist across the entire source of all your code-base. +Always be consistent in your use of whitespace. Use whitespace to improve +readability. + +- Never mix spaces and tabs for indentation. Stick to your choice without fail. (**Preference: tabs**) +- Choose the number of preferred characters used per indentation level. (**Preference: 4 spaces**) + +.. warning:: + +configure your editor to "show invisibles" or to automatically remove end-of-line whitespace. The use of an `EditorConfig `_ file is being used to help maintain the basic whitespace conventions. + + +As well as indentation, we can provide a lot of information through liberal and +judicious use of whitespace between rulesets. We use: + +- One (1) empty line between closely related rulesets. +- Two (2) empty lines between loosely related rulesets. + +For example: + +.. code-block:: scss + + //------------------------------------------------------------------------------ + // #FOO + //------------------------------------------------------------------------------ + + .foo { } + + .foo__bar { } + + + .foo--baz { } + + +There should never be a scenario in which two rulesets do not have an empty line +between them. This would be incorrect: + +.. code-block:: scss + + .foo { } + .foo__bar { } + .foo--baz { } + + + +Multiple Files +============== + +With the meteoric rise of preprocessors of late, more often is the case that +developers are splitting CSS across multiple files. + +Even if not using a preprocessor, it is a good idea to split discrete chunks of +code into their own files, which are concatenated during a build step. + +We follow the ITCSS principles for the organization of our code and as such +everything is broken up into partials. All partials are to be named to reflect +the contained component/module and lead by an underscore(`_`) to prevent self +rendering. + + +Commenting +========== + +**CSS needs more comments.** + +The cognitive overhead of working with CSS is huge. With so much to be aware of, +and so many project-specific nuances to remember, the worst situation most +developers find themselves in is being the-person-who-didn’t-write-this-code. +Remembering your own classes, rules, objects, and helpers is manageable to an +extent, but anyone inheriting CSS barely stands a chance. + +This is why well commented code is extremely important. Take time to describe +components, how they work, their limitations, and the way they are constructed. +Don't leave others in the project guessing as to the purpose of uncommon or +non-obvious code. + +Comment style should be simple and consistent within the code base. + +- Place comments on a new line above their subject. +- Keep line-length to a sensible maximum, e.g., 80 columns. +- Make liberal use of comments to break CSS code into discrete sections. +- Use "sentence case" comments and consistent text indentation. + +As CSS is something of a declarative language that doesn’t really leave much of +a paper-trail, it is often hard to discern—from looking at the CSS alone— + +- whether some CSS relies on other code elsewhere; +- what effect changing some code will have elsewhere; +- where else some CSS might be used; +- what styles something might inherit (intentionally or otherwise); +- what styles something might pass on (intentionally or otherwise); +- where the author intended a piece of CSS to be used. + +This doesn’t even take into account some of CSS’ many quirks—such as various +sates of `overflow` triggering block formatting context, or certain transform +properties triggering hardware acceleration—that make it even more baffling to +developers inheriting projects. + +As a result of CSS not telling its own story very well, it is a language that +really does benefit from being heavily commented. + +As a rule, you should comment anything that isn’t immediately obvious from the +code alone. That is to say, there is no need to tell someone that `color: red;` +will make something red, but if you’re using `overflow: hidden;` to clear +floats—as opposed to clipping an element’s overflow—this is probably something +worth documenting. + +.. warning:: + +Tip: you can configure your editor to provide you with shortcuts to output agreed-upon comment patterns. + +Comment Example: + +.. code-block:: scss + + //------------------------------------------------------------------------------ + // #[LAYER]: PARTIAL NAME + //------------------------------------------------------------------------------ + // #description + // + // This is a description of the PARTIAL + // + //------------------------------------------------------------------------------ + + // + // #settings + + // Layout Variables + $variable: [value] + + // Theme Variables + $variable: [value] + + // + // #scss + + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } + + // + // Section Block Comment + //------------------------------------------------------------------------------ + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } + + + +Low-level +--------- + +Oftentimes we want to comment on specific declarations (i.e. lines) in a +ruleset. To do this we use a kind of reverse footnote. Here is a more complex +comment detailing the larger site headers mentioned above: + +.. code-block:: scss + + // + // 1. Allow us to style box model properties. + // 2. Line different sized buttons up a little nicer. + // 3. Make buttons inherit font styles (often necessary when styling `input`s as + // buttons). + // 4. Reset/normalize some styles. + // 5. Force all button-styled elements to appear clickable. + // 6. Fixes odd inner spacing in IE7. + // 7. Subtract the border size from the padding value so that buttons do not + // grow larger as we add borders. + // 8. Prevent button text from being selectable. + // 9. Prevent deafult browser outline halo + // + .o-btn { + @include type(button); + @include shadow(2); + line-height: unitless($btn-height, map-get(map-get($type-styles, button), font-size)); + text-align: center; // [4] + vertical-align: middle; // [2] + white-space: nowrap; + text-decoration: none; // [4] + background-color: $btn-background-color; + border: none; + border-radius: $btn-border-radius; + outline: none; // [9] + color: $btn-text-color; + position: relative; + display: inline-block; // [1] + overflow: hidden; // [6] + min-width: $btn-min-width; + margin: 0; // [4] + padding: 0 $btn-spacing; // [7] + cursor: pointer; + user-select: none; // [8] + transition: + box-shadow 0.2s $animation-curve-fast-out-linear-in, + background-color 0.2s $default-animation-curve, + color 0.2s $default-animation-curve; + will-change: box-shadow; + } + + +These types of comment allow us to keep all of our documentation in one place +whilst referring to the parts of the ruleset to which they belong. + + +Titling +------- + +Begin every new major section of a CSS project with a title: + +.. code-block:: scss + + //------------------------------------------------------------------------------ + // #SECTION-TITLE + //------------------------------------------------------------------------------ + + .selector { } + + +The title of the section is prefixed with a hash (`#`) symbol to allow us to +perform more targeted searches (e.g. `grep`, etc.): instead of searching for +just `SECTION-TITLE`—which may yield many results—a more scoped search of +`#SECTION-TITLE` should return only the section in question. + +Leave a carriage return between this title and the next line of code (be that a +comment, some Sass, or some CSS). + + +Preprocessor Comments +--------------------- + +With most—if not all—preprocessors, we have the option to write comments that +will not get compiled out into our resulting CSS file. As a rule, use these +comments to speed up and prevent errors in the minification step. + + +Syntax and Formatting +===================== + +One of the simplest forms of a styleguide is a set of rules regarding syntax and +formatting. Having a standard way of writing (literally writing) CSS means that +code will always look and feel familiar to all members of the team. + +Further, code that looks clean feels clean. It is a much nicer environment to +work in, and prompts other team members to maintain the standard of cleanliness +that they found. Ugly code sets a bad precedent. + +The chosen code format must ensure that code is: easy to read; easy to clearly +comment; minimizes the chance of accidentally introducing errors; and results in +useful diffs and blames. + +At a very high-level, we want + +- Tab (4 space width) indents; +- 80 character wide columns; +- multi-line CSS; +- a meaningful use of comments & whitespace. + + +Anatomy of a Ruleset +-------------------- + +Before we discuss how we write out our rulesets, let’s first familiarize ourselves with the relevant terminology: + +The following is a ``[ruleset]`` + +.. code-block:: text + + [selector], + [selector] { + [property]: [value]; | + [property]: [value]; | <- [declaration-block] + [property]: [value]; | + [<--declaration--->] + } + + + +Formatting +--------- + +- Use one discrete selector per line in multi-selector rulesets. +- The opening brace (``{``) should be on the same line as our last selector. +- Include a single space before the opening brace (``{``). +- Include properties and values on the same line. +- Include one declaration per line in a declaration block. +- Use one level of indentation for each declaration. +- Include a single space after the colon (``:``) of a declaration. +- Use lowercase hex values, e.g., #abc123. +- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""``. +- Always quote attribute values in selectors, e.g., ``input[type="checkbox"]``. +- Avoid specifying units for zero-values, e.g., ``margin: 0``. +- Always use leading zeros, e.g, ``font-size: 0.875rem`` +- Include a space after each comma(``,``) in comma-separated property or function values. +- Include a semi-colon(``;``) at the end of every declaration including the last in a declaration block. +- Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line. +- Separate each ruleset by a blank line. + +Example: + +.. code-block:: scss + + .selector-1, + .selector-2, + .selector-3[type="text"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + padding: 0; + font-family: helvetica, arial, sans-serif; + color: #333333; + background: #ffffff; + background: linear-gradient(#ffffff, rgba(0, 0, 0, 0.8)); + } + + .selector-a, + .selector-b { + padding: 10px; + } + + +This format seems to be the largely universal standard (except for variations in +indentation). + +As such, the following would be incorrect: + +.. code-block:: scss + + .foo, .foo-bar, .baz + { + display:block; + background-color:green; + color:red } + + +Problems here include + +- 2 spaces instead of tabs (4 space width). +- selectors on the same line. +- the opening brace (``{``) on its own line. +- the closing brace (``}``) does not sit on its own line. +- the last semi-colon (``;``) is missing. +- no spaces after colons (``:``). + + +Multi-line CSS +-------------- + +CSS should be written across multiple lines, except in very specific +circumstances. There are a number of benefits to this: + +- A reduced chance of merge conflicts, because each piece of functionality exists on its own line. +- More ‘truthful’ and reliable ``diffs``, because one line only ever carries one change. + +Exceptions to this rule should be fairly apparent, such as similar rulesets +that only carry one declaration each, for example: + +.. code-block:: css + + .icon { + display: inline-block; + width: 16px; + height: 16px; + background-image: url(/img/sprite.svg); + } + + .icon-home { background-position: 0 0; } + .icon-person { background-position: -16px 0; } + .icon-files { background-position: 0 -16px; } + .icon-settings { background-position: -16px -16px; } + + +These types of ruleset benefit from being single-lined because + +- they still conform to the one-reason-to-change-per-line rule; +- they share enough similarities that they don’t need to be read as thoroughly as other rulesets—there is more benefit in being able to scan their selectors, which are of more interest to us in these cases. + + +Declaration order +----------------- + +declarations are to be consistently ordered by related property declarations +following the order + +1. Typographic +2. Visual +3. Positioning +4. Box model +5. Misc + +Example: + +.. code-block:: scss + + .declaration-order { + /* Typography */ + font: normal 13px "Helvetica Neue", sans-serif; + line-height: 1.5; + text-align: center; + + /* Visual */ + background-color: #f5f5f5; + border: 1px solid #e5e5e5; + border-radius: 3px; + color: #333333; + + /* Positioning */ + position: absolute; + z-index: 100; + top: 0; + right: 0; + bottom: 0; + left: 0; + + /* Box-model */ + display: block; + float: right; + width: 100px; + height: 100px; + margin: 0; + padding: 8px; + + /* Misc */ + content: "-"; + } + + + +Proper Use of units +------------------- + +CSS allows for the use of several different unit types. As such it can get +confusing when using more than one type of unit through out the project. For +that reason its beneficial to stick to a stick set of rules for what unit types +are to be used for certain selectors. + +Furthermore there are certain reasons to use or avoid using specific units in +certain places. + +EM +++ +The 'em' unit. This is a very problematic unit which reeks havoc on countless +projects due to the way its calculated. As such this unit type must be avoid +except for very very minimal use cases. We prevent the use of ``em`` except for +``letter-spaceing`` & ``word-spacing``. It is also used for icon sizing but that is +an edge case. + +Line-heights +++++++++++++ + +All line-heights are to be specified as unitless in order to prevent in proper +inheritance. By nature when using units with line-heights the children inherit +by default. This can lead to unwanted effects and bloated code. A ``sass`` +function called ``unitless`` is provided which will convert px values for +convenience, but for clarity the math is simply + +.. code-block:: scss + + line-height: (desired px value) / (current elements font-size) + + +Font-size ++++++++++ + +All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. All px +values will be converted to ``rem`` during the build process as ``rem`` provide for +control in responsive situations. + +Margins & Paddings + +++++++++++++++++++ +All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` All +px values will be converted to ``rem`` during the build process as `rem` provide +for control in responsive situations. + +PX +++ +All ``px`` will be whole numbers. Browsers do not render ``px`` in fractional values +despite what you browser may say it is. Only calculated values will display as +fractional ``px``. For clarification a calculated value would be units like ``rem``, +``em``, ``%``, & even ``unitless`` as is the case with line-heights. + +Dimensions +++++++++++ + +All dimensional values ``width``, ``min-width``, ``height``, & ``min-height`` should be +specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, but they are still +on the fringe of browser acceptance, as such fallbacks in ``px`` or ``%`` are +required. These values will remain as px if specified. This is done as ``height`` +is more effectively and appropriately controlled via the ``line-height`` property, +and ``width`` is better specified using the objects box-model via ``padding`` unless +its fluid in which ``100%`` can be specified or u can also use +``left: 0; right: 0;`` + + + +Indenting Sass +++++++++++++++ + +Sass provides nesting functionality. That is to say, by writing this: + +.. code-block:: css + + .foo { + color: red; + + .bar { + color: blue; + } + } + + +…we will be left with this compiled CSS: + +.. code-block:: css + + .foo { color: red; } + .foo .bar { color: blue; } + + +When indenting Sass, we stick to the same two indentation, and we also leave a +blank line before and after the nested ruleset. + + +**N.B.** Nesting in Sass should be avoided in most cases. See `Specificity`_ for more details. + + +Enforcing standardization +------------------------- + +Our project makes use of several tools to lint and to keep us to the standards. + +1. `stylelint.io `_ +++++++++++++++++++++++++++++++++++++++++++++ +.. note:: + +This is used to provide detailed linting for our standards via the ``.stlyelintrc`` file in the root of the project. + +2. `postcss-sorting `_ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +.. note:: + +This is used to provide automatic sorting to our declaration order via the ``.postcss-sorting.json`` file in the root of the project. + +3. `postcss-pxtorem `_ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +.. note:: + +This is used to ensure the proper units are consistently used throughout the project during the build process via the ``gulp`` as well as on save in your editor. + +4. `stylefmt `_ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +.. note:: + +This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. + +.. warning:: + +As a **NOTE** our editor of choice is `ATOM `_ which provides useful plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information From 01953cd9c5608bce253e3e7704b41e4a489035b9 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 7 Sep 2017 16:48:56 +0200 Subject: [PATCH 10/98] add css naming conventions --- development/development/css_naming.rst | 209 +++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 development/development/css_naming.rst diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst new file mode 100644 index 00000000..874f7079 --- /dev/null +++ b/development/development/css_naming.rst @@ -0,0 +1,209 @@ +Naming Conventions +================== + +Naming conventions in CSS are hugely useful in making your code more strict, +more transparent, and more informative. + +A good naming convention will tell you and your team + +- what type of thing a class does; +- where a class can be used; +- what (else) a class might be related to. + +The naming convention we follow are as follows + +- Hyphen (`-`) delimited strings. +- Layer namespacing +- A variation on BEM-like naming for action modifiers + +It’s worth noting that not all the naming convention are normally useful +in the CSS-side of development; they really come into their own when viewed in +HTML. + +Hyphen Delimited +---------------- + +All strings in classes are delimited with a hyphen (`-`), like so: + +.. code-block:: css + + .page-head { } + + .sub-content { } + + +Camel case and underscores are not used for regular classes; the following are +incorrect: + +.. code-block:: css + + .pageHead { } + + .sub_content { } + + +Modified BEM-like Naming +------------------------ + +For larger, more interrelated pieces of UI that require a number of classes, we +use a modified BEM-like naming convention. + +BEM, meaning Block, Element, Modifier, is a front-end methodology coined by +developers working at Yandex. Whilst BEM is a complete methodology, here we are +only concerned with its naming convention. Further, the naming convention here +only is BEM-like; the principles are exactly the same, but the actual syntax +differs. + +BEM splits components’ classes into three groups: + +- Block: The sole root of the component. +- Element: A component part of the Block. +- Modifier: A variant or extension of the Block. + +To take an analogy (note, not an example): + +.. code-block:: css + + .dropdown { } + .dropdown-item { } + .dropdown--active { } + + +Elements are delimited with two (hyphens (`-`), and Modifiers are delimited by +two (2) hyphens (`--`). + +Here we can see that `.dropdown {}` is the Block; it is the sole root of a +discrete entity. `.dropdown-item {}` is an Element; it is a smaller part of the +`.dropdown {}` Block. Finally, `.dropdown--active {}` is a Modifier; it is a +specific variant of the `.dropdown {}` Block. + +#### Starting Context + +Your Block context starts at the most logical, self-contained, discrete +location. To continue with our dropdown-based analogy, we’d not have a class +like `.header-dropdown {}`, as the header is another, much higher context. We’d +probably have separate Blocks, like so: + +.. code-block:: css + + .header { } + + .header-nav { } + + + .dropdown { } + + .dropdown-item { } + + +If we did want to denote a `.dropdown {}` inside a `.header {}`, it is more +correct to use a selector like `.header .dropdown {}` which bridges two Blocks +than it is to increase the scope of existing Blocks and Elements. + +A more realistic example of properly scoped blocks might look something like +this, where each chunk of code represents its own Block: + +.. code-block:: css + + .page { } + + + .content { } + + + .footer { } + + .footer-copyright { } + + +Incorrect notation for this would be: + +.. code-block:: css + + .page { } + + .page-content { } + + .page-footer { } + + .page-copyright { } + + +It is important to know when BEM scope starts and stops. As a rule, BEM applies +to self-contained, discrete parts of the UI. + +More Layers ++++++++++++ + +If we were to add another Element—called, let’s say, `.dropdown-link {}`—to +this `.dropdown {}` component, we would not need to step through every layer of +the DOM. That is to say, the correct notation would be `.dropdown-link {}`, and +not `.dropdown-item-link {}`. Your classes do not reflect the full paper-trail +of the DOM. + + +### Layer Namespacing + +There are a number of common problems when working with CSS at scale, but the +major two that namespacing aims to solve are clarity and confidence: + +- **Clarity:** How much information can we glean from the smallest possible source? Is our code self-documenting? Can we make safe assumptions from a single context? How much do we have to rely on external or supplementary information in order to learn about a system? +- **Confidence:** Do we have enough knowledge about a system to be able to safely interface with it? Do we know enough about our code to be able to confidently make changes? Do we have a way of knowing the potential side effects of making a change? Do we have a way of knowing what we might be able to remove? + +This gets further complicated when dealing with +[ITCSS](https://www.youtube.com/watch?v=1OKZOV-iLj4). Knowing what layer a +class is coming from is not always apparent. To combat this and provide complete +transparency we use layer based namespacing. + +In no particular order, here are the individual namespaces and a brief +description. We’ll look at each in more detail in a moment, but the following +list should acquaint you. + +- `o-`: Signify that something is an Object, and that it may be used in any number of unrelated contexts to the one you can currently see it in. Making modifications to these types of class could potentially have knock-on effects in a lot of other unrelated places. Tread carefully. +- `c-`: Signify that something is a Component. This is a concrete, implementation-specific piece of UI. All of the changes you make to its styles should be detectable in the context you’re currently looking at. Modifying these styles should be safe and have no side effects. +- `u-`: Signify that this class is a Utility class. It has a very specific role (often providing only one declaration) and should not be bound onto or changed. It can be reused and is not tied to any specific piece of UI. You will probably recognize this namespace from libraries and methodologies like `SUITcss `_. +- `t-`: Signify that a class is responsible for adding a Theme to a view. It lets us know that UI Components’ current cosmetic appearance may be due to the presence of a theme. Vastly improves templating for large projects +- `s-`: Signify that a class creates a new styling context or Scope. Similar to a Theme, but not necessarily cosmetic, these should be used sparingly—they can be open to abuse and lead to poor CSS if not used wisely. +- `is-`, `has-`: Signify that the piece of UI in question is currently styled a certain way because of a state or condition. This stateful namespace is gorgeous, and comes from `SMACSS `_. It tells us that the DOM currently has a temporary, optional, or short-lived style applied to it due to a certain state being invoked. +- `_`: Signify that this class is the worst of the worst—a hack! Sometimes, although incredibly rarely, we need to add a class in our markup in order to force something to work. If we do this, we need to let others know that this class is less than ideal, and hopefully temporary (i.e. do not bind onto this). +- `js`-: Signify that this piece of the DOM has some behavior acting upon it, and that JavaScript binds onto it to provide that behavior. If you’re not a developer working with JavaScript, leave these well alone. + +Even from this short list alone, we can see just how much more information we +can communicate to developers simply by placing a character or two at the front +of our existing classes. + + +**Further Reading** + +- `UI Selector Namspacing `_ + + +JavaScript Hooks +++++++++++++++++ + +As a rule, it is unwise to bind your CSS and your JS onto the same class in +your HTML. This is because doing so means you can’t have (or remove) one +without (removing) the other. It is much cleaner, much more transparent, and +much more maintainable to bind your JS onto specific classes. + +I have known occasions before when trying to refactor some CSS has unwittingly +removed JS functionality because the two were tied to each other—it was +impossible to have one without the other. + +Typically, these are classes that are prepended with `js-`, for example: + +.. code-block:: html + + + + +This means that we can have an element elsewhere which can carry with style of +`.btn {}`, but without the behaviour of `.js-btn`. + +`data-*` Attributes ++++++++++++++++++++ + +A common practice is to use `data-*` attributes as JS hooks, but this is +incorrect. `data-*` attributes, as per the spec, are used to store custom +data private to the page or application'* (emphasis Harry Roberts). `data-*` +attributes are designed to store data, not be bound to. From 8d9e75230796b0ee172c41081a7e29ac135c09dc Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Thu, 7 Sep 2017 16:49:04 +0200 Subject: [PATCH 11/98] add css selector intnet --- development/development/css_selectors.rst | 370 ++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 development/development/css_selectors.rst diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst new file mode 100644 index 00000000..c0cff7e3 --- /dev/null +++ b/development/development/css_selectors.rst @@ -0,0 +1,370 @@ +CSS Selectors +============= + +Perhaps somewhat surprisingly, one of the most fundamental, critical aspects of +writing maintainable and scalable CSS is selectors. Their specificity, their +portability, and their reusability all have a direct impact on the mileage we +will get out of our CSS, and the headaches it might bring us. + +Selector Intent +--------------- + +It is important when writing CSS that we scope our selectors correctly, and that +we’re selecting the right things for the right reasons. Selector Intent is the +process of deciding and defining what you want to style and how you will go +about selecting it. For example, if you are wanting to style your website’s main +navigation menu, a selector like this would be incredibly unwise: + +.. code-block:: css + + header ul { } + + +This selector’s intent is to style any `ul` inside any `header` element, whereas +our intent was to style the site’s main navigation. This is poor Selector +Intent: you can have any number of `header` elements on a page, and they in +turn can house any number of `ul`, so a selector like this runs the risk of +applying very specific styling to a very wide number of elements. This will +result in having to write more CSS to undo the greedy nature of such a selector. + +A better approach would be a selector like: + +.. code-block:: css + + .site-nav { } + + +An unambiguous, explicit selector with good Selector Intent. We are explicitly +selecting the right thing for exactly the right reason. + +Poor Selector Intent is one of the biggest reasons for headaches on CSS +projects. Writing rules that are far too greedy—and that apply very specific +treatments via very far reaching selectors—causes unexpected side effects and +leads to very tangled stylesheets, with selectors overstepping their intentions +and impacting and interfering with otherwise unrelated rulesets. + +CSS cannot be encapsulated, it is inherently leaky, but we can mitigate some of +these effects by not writing such globally-operating selectors: **your selectors +should be as explicit and well reasoned as your reason for wanting to select +something.** + +Reusability +----------- + +With a move toward a more component-based approach to constructing UIs, the idea +of reusability is paramount. We want the option to be able to move, recycle, +duplicate, and syndicate components across our projects. + +To this end, we make heavy use of classes. IDs, as well as being hugely +over-specific, cannot be used more than once on any given page, whereas classes +can be reused an infinite amount of times. Everything you choose, from the type +of selector to its name, should lend itself toward being reused. + +Location Independence +--------------------- + +Given the ever-changing nature of most UI projects, and the move to more +component-based architectures, it is in our interests not to style things based +on where they are, but on what they are. That is to say, our components’ styling +should not be reliant upon where we place them—they should remain entirely +location independent. + +Let’s take an example of a call-to-action button that we have chosen to style +via the following selector: + +.. code-block:: css + + .promo a { } + + +Not only does this have poor Selector Intent—it will greedily style any and +every link inside of a `.promo` to look like a button—it is also pretty wasteful +as a result of being so locationally dependent: we can’t reuse that button with +its correct styling outside of `.promo` because it is explicitly tied to that +location. A far better selector would have been: + +.. code-block:: css + + .btn { } + + +This single class can be reused anywhere outside of `.promo` and will always +carry its correct styling. As a result of a better selector, this piece of UI is +more portable, more recyclable, doesn’t have any dependencies, and has much +better Selector Intent. **A component shouldn’t have to live in a certain place +to look a certain way.** + +Portability +----------- + +Reducing, or, ideally, removing, location dependence means that we can move +components around our markup more freely, but how about improving our ability to +move classes around components? On a much lower level, there are changes we can +make to our selectors that make the selectors themselves—as opposed to the +components they create—more portable. Take the following example: + +.. code-block:: css + + input.btn { } + + +This is a _qualified_ selector; the leading `input` ties this ruleset to only +being able to work on `input` elements. By omitting this qualification, we allow +ourselves to reuse the `.btn` class on any element we choose, like an `a`, for +example, or a `button`. + +Qualified selectors do not lend themselves well to being reused, and every +selector we write should be authored with reuse in mind. + +Of course, there are times when you may want to legitimately qualify a +selector—you might need to apply some very specific styling to a particular +element when it carries a certain class, for example: + +.. code-block:: css + + /** + * Embolden and colour any element with a class of `.error`. + */ + .error { + color: red; + font-weight: bold; + } + + /** + * If the element is a `div`, also give it some box-like styling. + */ + div.error { + padding: 10px; + border: 1px solid; + } + + +This is one example where a qualified selector might be justifiable, but I would +still recommend an approach more like: + +.. code-block:: css + + /** + * Text-level errors. + */ + .error-text { + color: red; + font-weight: bold; + } + + /** + * Elements that contain errors. + */ + .error-box { + padding: 10px; + border: 1px solid; + } + + +This means that we can apply `.error-box` to any element, and not just a +`div`—it is more reusable than a qualified selector. + +Quasi-Qualified Selectors ++++++++++++++++++++++++++ + +One thing that qualified selectors can be useful for is signaling where a class +might be expected or intended to be used, for example: + +.. code-block:: css + + ul.nav { } + + +Here we can see that the `.nav` class is meant to be used on a `ul` element, and +not on a `nav`. By using _quasi-qualified selectors_ we can still provide that +information without actually qualifying the selector: + +.. code-block:: css + + /*ul*/.nav { } + + +By commenting out the leading element, we can still leave it to be read, but +avoid qualifying and increasing the specificity of the selector. + +Naming +------ + +As Phil Karlton once said + +.. note:: + +'There are only two hard things in Computer Science: cache invalidation and naming things.' + +I won’t comment on the former claim here, but the latter has plagued me for +years. My advice with regard to naming things in CSS is to pick a name that is +sensible, but somewhat ambiguous: aim for high reusability. For example, instead +of a class like `.site-nav`, choose something like `.primary-nav`; rather than +`.footer-links`, favor a class like `.sub-links`. + +The differences in these names is that the first of each two examples is tied to +a very specific use case: they can only be used as the site’s navigation or the +footer’s links respectively. By using slightly more ambiguous names, we can +increase our ability to reuse these components in different circumstances. + +To quote Nicolas Gallagher: + +.. note:: + +Tying your class name semantics tightly to the nature of the content has already +reduced the ability of your architecture to scale or be easily put to use by +other developers. + +That is to say, we should use sensible names—classes like `.border` or `.red` +are never advisable—but we should avoid using classes which describe the exact +nature of the content and/or its use cases. **Using a class name to describe +content is redundant because content describes itself.** + +The debate surrounding semantics has raged for years, but it is important that +we adopt a more pragmatic, sensible approach to naming things in order to work +more efficiently and effectively. Instead of focussing on ‘semantics’, look more +closely at sensibility and longevity—choose names based on ease of maintenance, +not for their perceived meaning. + +Name things for people; they’re the only things that actually read your classes +(everything else merely matches them). Once again, it is better to strive for +reusable, recyclable classes rather than writing for specific use cases. Let’s +take an example: + +.. code-block:: css + + /** + * Runs the risk of becoming out of date; not very maintainable. + */ + .blue { color: blue; } + + /** + * Depends on location in order to be rendered properly. + */ + .header span { color: blue; } + + /** + * Too specific; limits our ability to reuse. + */ + .header-color { color: blue; } + + /** + * Nicely abstracted, very portable, doesn’t risk becoming out of date. + */ + .highlight-color { color: blue; } + + +It is important to strike a balance between names that do not literally describe +the style that the class brings, but also ones that do not explicitly describe +specific use cases. Instead of `.home-page-panel`, choose `.masthead`; instead +of `.site-nav`, favor `.primary-nav`; instead of `.btn-login`, opt for +`.btn-primary`. + + +Selector Performance +-------------------- + +A topic which is—with the quality of today’s browsers—more interesting than it +is important, is selector performance. That is to say, how quickly a browser +can match the selectors your write in CSS up with the nodes it finds in the DOM. + +Generally speaking, the longer a selector is (i.e. the more component parts) +the slower it is, for example: + +.. code-block:: css + + body.home div.header ul { } + + +…is a far less efficient selector than: + +.. code-block:: css + + .primary-nav { } + + +This is because browsers read CSS selectors right-to-left. A browser will read +the first selector as + +- find all `ul` elements in the DOM; +- now check if they live anywhere inside an element with a class of `.header`; +- next check that `.header` class exists on a `div` element; +- now check that that all lives anywhere inside any elements with a class of `.home`; +- finally, check that `.home` exists on a `body` element. + +The second, in contrast, is simply a case of the browser reading find all the +elements with a class of `.primary-nav`. + +To further compound the problem, we are using descendant selectors (e.g. +`.foo .bar {}`). The upshot of this is that a browser is required to start with +the rightmost part of the selector (i.e. `.bar`) and keep looking up the DOM +indefinitely until it finds the next part (i.e. `.foo`). This could mean +stepping up the DOM dozens of times until a match is found. + +This is just one reason why +**nesting with preprocessors is often a false economy**; as well as making +selectors unnecessarily more specific, and creating location dependency, it +also creates more work for the browser. + +By using a child selector (e.g. `.foo > .bar {}`) we can make the process much +more efficient, because this only requires the browser to look one level higher +in the DOM, and it will stop regardless of whether or not it found a match. + +The Key Selector +++++++++++++++++ + +Because browsers read selectors right-to-left, the rightmost selector is often +critical in defining a selector’s performance: this is called the key selector. + +The following selector might appear to be highly performant at first glance. It +uses an ID which is nice and fast, and there can only ever be one on a page, so +surely this will be a nice and speedy lookup—just find that one ID and then +style everything inside of it: + +.. code-block:: css + + #foo * { } + + +The problem with this selector is that the key selector (`*`) is very, very far +reaching. What this selector actually does is find every single node in the DOM +(even ``, `<link>`, and `<head>` elements; everything) and then looks to +see if it lives anywhere at any level within #foo. This is a very, very +expensive selector, and should most likely be avoided or rewritten. + +Thankfully, by writing selectors with good +**Selector Intent**, we are probably +avoiding inefficient selectors by default; we are very unlikely to have greedy +key selectors if we’re targeting the right things for the right reason. + +That said, however, CSS selector performance should be fairly low on your list +of things to optimize; browsers are fast, and are only ever getting faster, and +it is only on notable edge cases that inefficient selectors would be likely to +pose a problem. + +As well as their own specific issues, nesting, qualifying, and poor Selector +Intent all contribute to less efficient selectors. + +General Rules +------------- + +Your selectors are fundamental to writing good CSS. To very briefly sum up the +above sections: + +- **Select what you want explicitly**, rather than relying on circumstance or coincidence. Good Selector Intent will rein in the reach and leak of your styles. +- **Write selectors for reusability**, so that you can work more efficiently and reduce waste and repetition. +- **Do not nest selectors unnecessarily**, because this will increase specificity and affect where else you can use your styles. +- **Do not qualify selectors unnecessarily**, as this will impact the number of different elements you can apply styles to. +- **Keep selectors as short as possible**, in order to keep specificity down and performance up. + +Focussing on these points will keep your selectors a lot more sane and easy to +work with on changing and long-running projects. + +**Further Reading** + +- `Shoot to kill; CSS selector intent <http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/`_ +- `‘Scope’ in CSS <http://csswizardry.com/2013/05/scope-in-css/`_ +- `Keep your CSS selectors short <http://csswizardry.com/2012/05/keep-your-css-selectors-short/`_ +- `About HTML semantics and front-end architecture <http://nicolasgallagher.com/about-html-semantics-front-end-architecture/`_ +- `Naming UI components in OOCSS <http://csswizardry.com/2014/03/naming-ui-components-in-oocss/`_ +- `Writing efficient CSS selectors <http://csswizardry.com/2011/09/writing-efficient-css-selectors/`_ From a644e0de27fcf73d73d070414ef4484e7b4cc84c Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 7 Sep 2017 16:49:12 +0200 Subject: [PATCH 12/98] add css specificity info --- development/development/css_specificity.rst | 408 ++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 development/development/css_specificity.rst diff --git a/development/development/css_specificity.rst b/development/development/css_specificity.rst new file mode 100644 index 00000000..e1ce8290 --- /dev/null +++ b/development/development/css_specificity.rst @@ -0,0 +1,408 @@ +Specificity +=========== + +As we’ve seen, CSS isn’t the most friendly of languages: globally operating, +very leaky, dependent on location, hard to encapsulate, based on inheritance… +But! None of that even comes close to the horrors of specificity. + +No matter how well considered your naming, regardless of how perfect your +source order and cascade are managed, and how well you’ve scoped your rulesets, +just one overly-specific selector can undo everything. It is a gigantic +curveball, and undermines CSS’ very nature of the cascade, inheritance, and +source order. + +The problem with specificity is that it sets precedents and trumps that cannot +simply be undone. If we take the following example + +.. code-block:: css + + #content table { } + + +Not only does this exhibit poor +**Selector Intent**, we didn’t actually want every `table` in the `#content` +area. We wanted a specific type of `table` that just happened to live there. +This is a hugely over-specific selector. It becomes apparent, when we needed a +second type of `table`: + +.. code-block:: css + + #content table { } + + /** + * Uh oh! My styles get overwritten by `#content table {}`. + */ + .my-new-table { } + + +The first selector was trumping the specificity of the one defined after it, +working against CSS’ source-order based application of styles. In order to +remedy this, we have two main options. we could + +1. refactor the CSS and HTML to remove that ID; +2. write a more specific selector to override it. + +Unfortunately, refactoring would take a long time in a mature product and the +knock-on effects of removing this ID would be more substantial business cost +than the second option: just write a more specific selector. + +.. code-block:: css + + #content table { } + + #content .my-new-table { } + + +Now we have a selector that is even more specific still! And if we ever want to +override this one, we will need another selector of at least the same +specificity defined after it. We’ve started on a downward spiral. + +Specificity can, among other things, + +- limit your ability to extend and manipulate a codebase; +- interrupt and undo CSS’ cascading, inheriting nature; +- cause avoidable verbosity in your project; +- prevent things from working as expected when moved into different environments; +- lead to serious developer frustration. + +All of these issues are greatly magnified when working on a larger project with +a number of developers contributing code. + + +Keep It Low at All Times +------------------------ + +The problem with specificity isn’t necessarily that it’s high or low; it’s the +fact it is so variant and that it cannot be opted out of: the only way to deal +with it is to get progressively more specific—the notorious specificity wars we +looked at above. + +One of the single, simplest tips for an easier life when writing CSS, +particularly at any reasonable scale—is to always try to keep specificity as +low as possible at all times. Try to make sure there isn’t a lot of variance +between selectors in the codebase, and that all selectors strive for as low a +specificity as possible. + +Doing so will instantly help us tame and manage the project, meaning that no +overly-specific selectors are likely to impact or affect anything of a lower +specificity elsewhere. It also means we’re less likely to need to fight our way +out of specificity corners, and we’ll probably also be writing much smaller +stylesheets. + +Simple changes to the way we work include, but are not limited to, + +- not using IDs in your CSS; +- not nesting selectors; +- not qualifying classes; +- not chaining selectors. + +**Specificity can be wrangled and understood, but it is safer just to avoid it entirely.** + + +IDs in CSS +---------- + +If we want to keep specificity low, which we do, we have one really quick-win, +simple, easy-to-follow rule that we can employ to help us: + +.. warning:: + +**NEVER USE IDs in CSS** + +Not only are IDs inherently non-reusable, they are also vastly more specific +than any other selector, and therefore become specificity anomalies. Where the +rest of your selectors are relatively low specificity, your ID-based selectors +are, comparatively, much, much higher. + +In fact, to highlight the severity of this difference, see how one thousand +chained classes cannot override the specificity of a single ID: +`jsfiddle.net/0yb7rque <http://jsfiddle.net/csswizardry/0yb7rque/`_. + +.. warning:: + +(Please note that in Firefox you may see the text rendering in blue: this is a `known bug <https://twitter.com/codepo8/status/505004085398224896>`_, and an ID will be overridden by 256 chained classes.) + +.. note:: + +**N.B.** It is still perfectly okay to use IDs in HTML and JavaScript; it is only in CSS that they prove troublesome. + +It is often suggested that developers who choose not to use IDs in CSS merely +don’t understand how specificity works. This is as incorrect as it is +offensive: no matter how experienced a developer you are, this behavior cannot +be circumvented; no amount of knowledge will make an ID less specific. + +Opting into this way of working only introduces the chance of problems +occurring further down the line, and—particularly when working at scale—all +efforts should be made to avoid the potential for problems to arise. In a +sentence: + +**It is just not worth introducing the risk.** + + +Nesting +------- + +We’ve already looked at how nesting can lead to location dependent and +potentially inefficient code, but now it’s time to take a look at another of +its pitfalls: it makes selectors more specific. + +When we talk about nesting, we don’t necessarily mean preprocessor nesting, +like so: + +.. code-block:: scss + + .foo { + + .bar { } + + } + + +We’re actually talking about descendant or child selectors; selectors which +rely on a thing within a thing. That could look like any one of the following: + +.. code-block:: css + + /** + * An element with a class of `.bar` anywhere inside an element with a class of + * `.foo`. + */ + .foo .bar { } + + + /** + * An element with a class of `.module-title` directly inside an element with a + * class of `.module`. + */ + .module > .module-title { } + + + /** + * Any `li` element anywhere inside a `ul` element anywhere inside a `nav` + * element + */ + nav ul li { } + + +Whether you arrive at this CSS via a preprocessor or not isn’t particularly +important, but it is worth noting **that preprocessors tout this as a feature, +where it is actually to be avoided wherever possible.** + +Generally speaking, each part in a compound selector adds specificity. Ergo, +the fewer parts to a compound selector then the lower its overall specificity, +and we always want to keep specificity low. To quote Jonathan Snook: + +.. note:: + +…whenever declaring your styles, **use the least number of selectors required to style an element.** + +Let’s look at an example: + +.. code-block:: css + + .widget { + padding: 10px; + } + + .widget > .widget-title { + color: red; + } + + +To style an element with a class of `.widget-title`, we have a selector that +is twice as specific as it needs to be. That means that if we want to make any +modifications to `.widget-title`, we’ll need another at-least-equally specific +selector: + +.. code-block:: css + + .widget { ... } + + .widget > .widget-title { ... } + + .widget > .widget-title-sub { + color: blue; + } + + +Not only is this entirely avoidable—we caused this problem ourselves—we have a +selector that is literally double the specificity it needs to be. We used 200% +of the specificity actually required. And not only that, but this also leads to +needless verbosity in our code—more to send over the wire. + +.. warning:: + +As a rule, **if a selector will work without it being nested then do not nest it.** + + +Scope +----- + +One possible advantage of nesting—which, unfortunately, does not outweigh the +disadvantages of increased specificity—is that it provides us with a namespace +of sorts. A selector like `.widget .title` scopes the styling of `.title` to an +element that only exists inside of an element carrying a class of `.widget`. + +This goes some way to providing our CSS with scope and encapsulation, but does +still mean that our selectors are twice as specific as they need to be. A +better way of providing this scope would be via a namespace—which does not lead +to an unnecessary increase in specificity. + +Now we have better scoped CSS with minimal specificity—the best of both worlds. + +**Further Reading** + +- `‘Scope’ in CSS <http://csswizardry.com/2013/05/scope-in-css/>`_ + + +`!important` +------------ + +The word `!important` sends shivers down the spines of almost all front-end +developers. `!important` is a direct manifestation of problems with +specificity; it is a way of cheating your way out of specificity wars, but +usually comes at a heavy price. It is often viewed as a last resort—a +desperate, defeated stab at patching over the symptoms of a much bigger problem +with your code. + +The general rule is that `!important` is always a bad thing, but, to quote +Jamie Mason: + +.. note:: + +Rules are the children of principles. + +That is to say, a single rule is a simple, black-and-white way of adhering to a +much larger principle. When you’re starting out, the rule never use +`!important` is a good one. + +However, once you begin to grow and mature as a developer, you begin to +understand that the principle behind that rule is simply about keeping +specificity low. You’ll also learn when and where the rules can be bent… + +`!important` does have a place in CSS projects, but only if used sparingly and +proactively. + +Proactive use of `!important` is when it is used _before_ you’ve encountered +any specificity problems; when it is used as a guarantee rather than as a fix. + +For example: + +.. code-block:: css + + .one-half { + width: 50% !important; + } + + .hidden { + display: none !important; + } + + +These two helper, or _utility_, classes are very specific in their intentions: +you would only use them if you wanted something to be rendered at 50% width or +not rendered at all. If you didn’t want this behavior, you would not use these +classes, therefore whenever you do use them you will definitely want them to +win. + +Here we proactively apply `!important` to ensure that these styles always win. +This is the correct use of `!important` to guarantee that these trumps always +work, and don’t accidentally get overridden by something else more specific. + +Incorrect, reactive use of `!important` is when it is used to combat +specificity problems after the fact: applying `!important` to declarations +because of poorly architected CSS. For example, let’s imagine we have this HTML: + +.. code-block:: html + + <div class="content"> + <h2 class="heading-sub">...</h2> + </div> + +…and this CSS: + +.. code-block:: css + + .content h2 { + font-size: 2rem; + } + + .heading-sub { + font-size: 1.5rem !important; + } + +Here we can see how we’ve used `!important` to force our `.heading-sub {}` +styles to reactively override our `.content h2 {}` selector. This could have +been circumvented by any number of things, including using better Selector +Intent, or avoiding nesting. + +In these situations, it is preferable that you investigate and refactor any +offending rulesets to try and bring specificity down across the board, as +opposed to introducing such specificity heavyweights. + +.. warning:: + +**Only use** `!important` **proactively, not reactively.** + + +Hacking Specificity +------------------- + +With all that said on the topic of specificity, and keeping it low, it is +inevitable that we will encounter problems. No matter how hard we try, and how +conscientious we are, there will always be times that we need to hack and +wrangle specificity. + +When these situations do arise, it is important that we handle the hacks as +safely and elegantly as possible. + +In the event that you need to increase the specificity of a class selector, +there are a number of options. We could nest the class inside something else to +bring its specificity up. For example, we could use `.header .site-nav {}` to +bring up the specificity of a simple `.site-nav {}` selector. + +The problem with this, as we’ve discussed, is that it introduces location +dependency: these styles will only work when the `.site-nav` component is in +the `.header` component. + +Instead, we can use a much safer hack that will not impact this component’s +portability: we can chain that class with itself: + +.. code-block:: css + + .site-nav.site-nav { } + +This chaining doubles the specificity of the selector, but does not introduce +any dependency on location. + +In the event that we do, for whatever reason, have an ID in our markup that we +cannot replace with a class, select it via an attribute selector as opposed to +an ID selector. For example, let’s imagine we have embedded a third-party +widget on our page. We can style the widget via the markup that it outputs, but +we have no ability to edit that markup ourselves: + +.. code-block:: html + + <div id="third-party-widget"> + ... + </div> + +Even though we know not to use IDs in CSS, what other option do we have? We +want to style this HTML but have no access to it, and all it has on it is an ID. + +We do this: + +.. code-block:: css + + [id="third-party-widget"] { } + +Here we are selecting based on an attribute rather than an ID, and attribute +selectors have the same specificity as a class. This allows us to style based +on an ID, but without introducing its specificity. + +Do keep in mind that these are hacks, and should not be used unless you have no +better alternative. + +**Further Reading** + +- `Hacks for dealing with specificity <http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/'_ From e76f4c7fdc6175c0e138ec1aa4100bed4f7fe1b2 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 9 Sep 2017 16:48:35 +0200 Subject: [PATCH 13/98] fix some typos --- development/development/css_guidelines.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index 44160ff3..eedfa940 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -480,6 +480,7 @@ certain places. EM ++ + The 'em' unit. This is a very problematic unit which reeks havoc on countless projects due to the way its calculated. As such this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for @@ -508,8 +509,8 @@ values will be converted to ``rem`` during the build process as ``rem`` provide control in responsive situations. Margins & Paddings - ++++++++++++++++++ + All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` All px values will be converted to ``rem`` during the build process as `rem` provide for control in responsive situations. From 01122d3140e9234ddd6d967772eab94f93ba8d8c Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 5 Oct 2017 02:26:18 -0400 Subject: [PATCH 14/98] rebreakout all the css docs --- development/development/css_architecture.rst | 793 ++++++++++++++++++ development/development/css_guidelines.rst | 804 +++++++------------ development/development/css_naming.rst | 374 +++++---- development/development/css_selectors.rst | 751 +++++++++-------- development/development/css_specificity.rst | 704 +++++++++------- development/development/css_standards.rst | 362 +++++++++ 6 files changed, 2509 insertions(+), 1279 deletions(-) create mode 100644 development/development/css_architecture.rst create mode 100644 development/development/css_standards.rst diff --git a/development/development/css_architecture.rst b/development/development/css_architecture.rst new file mode 100644 index 00000000..7a26440d --- /dev/null +++ b/development/development/css_architecture.rst @@ -0,0 +1,793 @@ +Architectural Principles +------------------------ + +| You would be forgiven for thinking that an architecture for CSS is a + somewhat +| grandiose and unnecessary concept: why would something so simple, so +| straightforward, need something as complex or considered as an + architecture?! + +| Well, as we’ve seen, CSS’ simplicity, its looseness, and its unruly + nature mean +| that the best way of managing (reading, taming) it at any reasonable + scale is +| through a strict and specific architecture. A solid architecture can + help us +| control our specificity, enforce naming conventions, manage our source + order, +| create a sane development environment, and generally make managing our + CSS +| projects a lot more consistent and comfortable. + +| There is no tool, no preprocessor, no magic bullet, that will make + your CSS +| better on its own: a developer’s best tool when working with such a + loose +| syntax is self-discipline, conscientiousness, and diligence, and a + well-defined +| architecture will help enforce and facilitate these traits. + +| Architectures are large, overarching, principle-led collections of + smaller +| conventions which come together to provide a managed environment in + which code +| is written and maintained. Architectures are typically quite high + level, and +| leave implementation details—such as naming conventions or syntax and +| formatting, for example—to the team implementing it. + +| Most architectures are usually based around existing design patterns + and +| paradigms, and, more often than not, these paradigms were born of + computer +| scientists and software engineers. For all CSS isn’t ‘code’, and + doesn’t +| exhibit many traits that programming languages do, we find that we can + apply +| some of these same principles to our own work. + +| In this section, we’ll take a look at some of these design patterns + and +| paradigms, and how we can use them to reduce code—and increase code + reuse—in +| our CSS projects. + +High-level Overview +~~~~~~~~~~~~~~~~~~~ + +At a very high-level, our architecture should help you + +- provide a consistent and sane environment; +- accommodate change; +- grow and scale your codebase; +- promote reuse and efficiency; +- increased productivity. + +| Typically, this will mean a class-based and componentised + architecture, split +| up into manageable modules, probably using a preprocessor. Of course, + there is +| far more to an architecture than that, so let’s look at some + principles… + +Object-orientation +~~~~~~~~~~~~~~~~~~ + +| Object-orientation is a programming paradigm that breaks larger + programs up +| into smaller, in(ter)dependent objects that all have their own roles + and +| responsibilities. From Wikipedia: + +.. note:: + +Object-oriented programming (OOP) is a programming paradigm that +represents the concept of ‘objects’ […] which are usually instances of +classes, [and] are used to interact with one another to design +applications and computer programs. + +| When applied to CSS, we call it object-oriented CSS, or OOCSS. OOCSS + was coined +| and popularized by Nicole Sullivan, whose Media Object has become the + poster +| child of the methodology. + +| OOCSS deals with the separation of UIs into structure and skin: + breaking UI +| components into their underlying structural forms, and layering their + cosmetic +| forms on separately. This means that we can recycle common and + recurring design +| patterns very cheaply without having to necessarily recycle their + specific +| implementation details at the same time. OOCSS promotes reuse of code, + which +| makes us quicker, as well as keeping the size of our codebase down. + +| Structural aspects can be thought of like skeletons; common, recurring + frames +| that provide design-free constructs known as objects and abstractions. + Objects +| and abstractions are simple design patterns that are devoid of any + cosmetics; +| we abstract out the shared structural traits from a series of + components into a +| generic object. + +| Skin(Theme) is a layer that we (optionally) add to our structure in + order to +| give objects and abstractions a specific look-and-feel. + +Let’s look at an example: + +.. code:: css + + /** + * A simple, design-free button object. Extend this object with a `.btn--*` skin + * class. + */ + .btn { + display: inline-block; + padding: 1em 2em; + vertical-align: middle; + } + + + /** + * Positive buttons’ skin. Extends `.btn`. + */ + .btn-inverse { + background-color: green; + color: white; + } + +| Above, we can see how the ``.btn {}`` class simply provides structural + styling to +| an element, and doesn’t concern itself with any cosmetics. We + supplement the +| ``.btn {}`` object with a second class, such as ``.btn-inverse {}`` in + order to +| give that DOM node specific cosmetics: + +.. code:: html + + <button class="btn btn-inverse">Delete</button> + +| Favor the multiple-class approach over using something like + ``@extend``: using +| multiple classes in your markup—as opposed to wrapping the classes up + into one +| using a preprocessor—gives you a better paper-trail in your markup, + and allows +| you to see quickly and explicitly which classes are acting on a piece + of HTML; +| allows for greater composition in that classes are not tightly bound + to other +| styles in your CSS. Whenever you are building a UI component, try and + see if +| you can break it into two parts: one for structural styles (paddings, + layout, +| etc.) and another for skin (colors, typefaces, etc.). + +| As a rule its a reasonable practice to set defaults of all skin + classes on the +| objects and then use the modifiers to overwrite them. + +Further Reading +''''''''''''''' + +- `The media object saves hundreds of lines of code`_ +- `The flag object`_ +- `Naming UI components in OOCSS`_ + +The Single Responsibility Principle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| The single responsibility principle is a paradigm that, very loosely, + states +| that all pieces of code (in our case, classes) should focus on doing + one thing +| and one thing only. More formally: + +.. note:: + +…the single responsibility principle states that every context +(class, function, variable, etc.) should have a single responsibility, +and that responsibility should be entirely encapsulated by the context. + +| What this means for us is that our CSS should be composed of a series + of much +| smaller classes that focus on providing very specific and limited +| functionality. This means that we need to decompose UIs into their + smallest +| component pieces that each serve a single responsibility; they all do + just one +| job, but can be very easily combined and composed to make much more + versatile +| and complex constructs. Let’s take some example CSS that does not + adhere to the +| single responsibility principle: + +.. code:: css + + .error-message { + display: block; + padding: 10px; + border-top: 1px solid #ff0000; + border-bottom: 1px solid #ff0000; + background-color: #ffeeee; + color: #ff0000; + font-weight: bold; + } + + .success-message { + display: block; + padding: 10px; + border-top: 1px solid #00ff00; + border-bottom: 1px solid #00ff00; + background-color: #eeffee; + color: #00ff00; + font-weight: bold; + } + +| Here we can see that—despite being named after one very specific + use-case—these +| classes are handling quite a lot: layout, structure, and cosmetics. We + also +| have a lot of repetition. We need to refactor this in order to + abstract out +| some shared objects (OOCSS) and bring it more inline with the single +| responsibility principle. We can break these two classes out into four + much +| smaller responsibilities: + +.. code:: css + + .box { + display: block; + padding: 10px; + } + + + .message { + border-style: solid; + border-width: 1px 0; + font-weight: bold; + } + + .message-error { + background-color: #ffeeee; + color: #ff0000; + } + + .message-success { + background-color: #eeffee; + color: #00ff00; + } + +| Now we have a general abstraction for boxes which can live, and be + used, +| completely separately from our message component, and we have a base + message +| component that can be extended by a number of smaller responsibility + classes. +| The amount of repetition has been greatly reduced, and our ability to + extend +| and compose our CSS has been greatly increased. This is a great + example of +| OOCSS and the single responsibility principle working in tandem. + +| By focussing on single responsibilities, we can give our code much + more +| flexibility, and extending components’ functions becomes very simple + when +| sticking to the open/closed principle, which we’re going to look at + next. + +Further Reading +''''''''''''''' + +- `The single responsibility principle applied to CSS`_ + +The Open/Closed Principle +~~~~~~~~~~~~~~~~~~~~~~~~~ + +| The open/closed principle, in my opinion, is rather poorly named. It + is poorly +| named because 50% of the vital information is omitted from its title. + The +| open/closed principle states that + +.. note:: + +software entities (classes, modules, functions, etc.) should be open +for extension, but closed for modification. + +| See the most important words—extension and modification—are completely + missing +| from the name, which isn’t very useful at all. + +| Once you have trained yourself to remember what the words open and + closed +| actually relate to, you’ll find that open/closed principle remarkably + simple: +| any additions, new functionality, or features we add to our classes + should be +| added via extension—we should not modify these classes directly. This + really +| trains us to write bulletproof single responsibilities: because we + shouldn’t +| modify objects and abstractions directly, we need to make sure we get + them as +| simple as possible the first time. This means that we should never + need to +| actually change an abstraction—we’d simply stop using it—but any + slight +| variants of it can be made very easily by extending it. + +Let’s take an example: + +.. code:: css + + .box { + display: block; + padding: 10px; + } + + .box-large { + padding: 20px; + } + +Here we can see that the ``.box {}`` object is incredibly simple: we’ve +stripped it right back into one very small and very focussed +responsibility. To modify that box, we extend it with another class; +``.box--large {}``. Here the ``.box {}`` class is closed to +modification, but open to being extended. + +An incorrect way of achieving the same might look like this: + +.. code:: css + + .box { + display: block; + padding: 10px; + } + + .content .box { + padding: 20px; + } + +| Not only is this overly specific, locationally dependent, and + potentially +| displaying poor Selector Intent, we are modifying the ``.box {}`` + directly. We +| should rarely—if ever—find an object or abstraction’s class as a key + selector +| in a compound selector. + +A selector like ``.content .box {}`` is potentially troublesome because + +- it forces all ``.box`` components into that style when placed inside + of ``.content``, which means the modification is dictated to + developers, whereas developers should be allowed to opt into changes + explicitly; +- the ``.box`` style is now unpredictable to developers; the single + responsibility no longer exists because nesting the selector produces + a forced caveat. + +| All modifications, additions, and changes should always be opt-in, not +| mandatory. If you think something might need a slight adjustment to + take it +| away from the norm, provide another class which adds this + functionality. + +| When working in a team environment, be sure to write API-like CSS; + always +| ensure that existing classes remain backward compatible (i.e. no + changes at +| their root) and provide new hooks to bring in new features. Changing + the root +| object, abstraction, or component could have huge knock-on effects for +| developers making use of that code elsewhere, so never modify existing + code +| directly. + +| Exceptions may present themselves when it transpires that a root + object does +| need a rewrite or refactor, but it is only in these specific cases + that you +| should modify code. Remember: **open for extension; closed for + modification.** + +Further Reading +''''''''''''''' + +- `The open/closed principle applied to CSS`_ + +DRY +~~~ + +| DRY, which stands for Don’t Repeat Repeat Yourself, is a + micro-principle used +| in software development which aims to keep the repetition of key + information to +| a minimum. Its formal definition is that + +.. note:: + +every piece of knowledge must have a single, unambiguous, +authoritative representation within a system. + +| Although a very simple principle—in principle—DRY is often + misinterpreted as +| the necessity to never repeat the exact same thing twice at all in a + project. +| This is impractical and usually counterproductive, and can lead to + forced +| abstractions, over-thought and -engineered code, and unusual + dependencies. + +| The key isn’t to avoid all repetition, but to normalize and abstract + meaningful +| repetition. If two things happen to share the same declarations + coincidentally, +| then we needn’t DRY anything out; that repetition is purely + circumstantial and +| cannot be shared or abstracted. For example: + +.. code:: css + + .btn { + font-weight: bold; + display: inline-block; + padding: 1rem 2rem; + } + + [...] + + .page-title { + font-size: 3rem; + font-weight: bold; + line-height: 1.4; + } + + [...] + + .user-profile-title { + font-size: 1.2rem; + font-weight: bold; + line-height: 1.5; + } + +| From the above code, we can reasonably deduce that the + ``font-weight: bold;`` +| declaration appears three times purely coincidentally. To try and + create an +| abstraction, mixin, or ``@extend`` directive to cater for this + repetition would +| be overkill, and would tie these three rulesets together based purely + on +| circumstance. + +| However, imagine we’re using a web-font that requires + ``font-weight: bold;`` to +| be declared every time the ``font-family`` is: + +.. code:: css + + .btn { + font-family: "My Web Font", sans-serif; + font-weight: bold; + display: inline-block; + padding: 1rem 2rem; + } + + [...] + + .page-title { + font-family: "My Web Font", sans-serif; + font-size: 3rem; + font-weight: bold; + line-height: 1.4; + } + + [...] + + .user-profile-title { + font-family: "My Web Font", sans-serif; + font-size: 1.2rem; + font-weight: bold; + line-height: 1.5; + } + +| Here we’re repeating a more meaningful snippet of CSS; these two + declarations +| have to always be declared together. In this instance, we probably + would DRY +| out our CSS. + +| I would recommend using a mixin over ``@extend`` here because, even + though the +| two declarations are thematically grouped, the rulesets themselves are + still +| separate, unrelated entities: to use ``@extend`` would be to + physically group +| these unrelated rulesets together in our CSS, thus making the + unrelated related. + +Our mixin: + +.. code:: scss + + @mixin my-web-font() { + font-family: "My Web Font", sans-serif; + font-weight: bold; + } + + .btn { + @include my-web-font(); + display: inline-block; + padding: 1rem 2rem; + } + + [...] + + .page-title { + @include my-web-font(); + font-size: 3rem; + line-height: 1.4; + } + + [...] + + .user-profile__title { + @include my-web-font(); + font-size: 1.2rem; + line-height: 1.5; + } + +| Now the two declarations only exist once, meaning we’re not repeating +| ourselves. If we ever switch out our web-font, or move to a +| ``font-weight: normal;`` version, we only need to make that change in + one place. + +| In short, only DRY code that is actually, thematically related. Do not + try to +| reduce purely coincidental repetition: +| **duplication is better than the wrong abstraction.** + +Further Reading +''''''''''''''' + +- `Writing DRYer vanilla CSS`_ + +Composition over Inheritance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| Now that we’re used to spotting abstractions and creating single +| responsibilities, we should be in a great position to start composing + more +| complex composites from a series of much smaller component parts. + Nicole +| Sullivan likens this to using Lego; tiny, single responsibility pieces + which +| can be combined in a number of different quantities and permutations + to create +| a multitude of very different looking results. + +| This idea of building through composition is not a new one, and is + often +| referred to as composition over inheritance. This principle suggests + that +| larger systems should be composed from much smaller, individual parts, + rather +| than inheriting behavior from a much larger, monolithic object. This + should +| keep your code decoupled—nothing inherently relies on anything else. + +| Composition is a very valuable principle for an architecture to make + use of, +| particularly considering the move toward component-based UIs. It will + mean you +| can more easily recycle and reuse functionality, as well rapidly + construct +| larger parts of UI from a known set of composeable objects. Think back + to our +| error message example in the +| Single Responsibility Principle +| section; we created a complete UI component by composing a number of + much +| smaller and unrelated objects. + +The Separation of Concerns +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| The separation of concerns is a principle which, at first, sounds a + lot like +| the single responsibility principle. The separation of concerns states + that +| code should be broken up + +.. note:: + +into distinct sections, such that each section addresses a separate +concern. A concern is a set of information that affects the code of a +computer program. A program that embodies SoC well is called a modular +program. + +| Modular is a word we’re probably used to; the idea of breaking UIs and + CSS into +| much smaller, composeable pieces. The separation of concerns is just a + formal +| definition which covers the concepts of modularity and encapsulation + in code. +| In CSS this means building individual components, and writing code + which only +| focusses itself on one task at a time. + +The term was coined by Edsger W. Dijkstra, who rather elegantly said: + +.. note:: + +Let me try to explain to you, what to my taste is characteristic for +all intelligent thinking. It is, that one is willing to study in depth +an aspect of one’s subject matter in isolation for the sake of its own +consistency, all the time knowing that one is occupying oneself only +with one of the aspects. We know that a program must be correct and we +can study it from that viewpoint only; we also know that it should be +efficient and we can study its efficiency on another day, so to speak. +In another mood we may ask ourselves whether, and if so: why, the +program is desirable. But nothing is gained—on the contrary!—by tackling +these various aspects simultaneously. It is what I sometimes have called +‘the separation of concerns’, which, even if not perfectly possible, is +yet the only available technique for effective ordering of one’s +thoughts, that I know of. This is what I mean by ‘focusing one’s +attention upon some aspect’: it does not mean ignoring the other +aspects, it is just doing justice to the fact that from this aspect’s +point of view, the other is irrelevant. It is being one- and +multiple-track minded simultaneously. + +| Beautiful. The idea here is to focus fully on one thing at once; build + one +| thing to do its job very well whilst paying as little attention as + possible to +| other facets of your code. Once you have addressed and built all these + separate +| concerns in isolation—meaning they’re probably very modular, + decoupled, and +| encapsulated—you can begin bringing them together into a larger + project. + +| A great example is layout. If you are using a grid system, all of the + code +| pertaining to layout should exist on its own, without including + anything else. +| You’ve written code that handles layout, and that’s it: + +.. code:: html + + <div class="layout"> + + <div class="layout-item two-thirds"> + </div> + + <div class="layout-item one-third"> + </div> + + </div> + +| You will now need to write new, separate code to handle what lives + inside of +| that layout: + +.. code:: html + + <div class="layout"> + + <div class="layout-item two-thirds"> + <section class="content"> + ... + </section> + </div> + + <div class="layout-item one-third"> + <section class="sub-content"> + ... + </section> + </div> + + </div> + +| The separation of concerns allows you to keep code self-sufficient, + ignorant, +| and ultimately a lot more maintainable. Code which adheres to the + separation of +| concerns can be much more confidently modified, edited, extended, and +| maintained because we know how far its responsibilities reach. We know + that +| modifying layout, for example, will only ever modify layout—nothing + else. + +| The separation of concerns increases reusability and confidence whilst + reducing +| dependency. + +Misconceptions +^^^^^^^^^^^^^^ + +| There are, I feel, a number of unfortunate misconceptions surrounding + the +| separation of concerns when applied to HTML and CSS. They all seem to + revolve +| around some format of: + +.. note:: + +Using classes for CSS in your markup breaks the separation of +concerns. + +| Unfortunately, this is simply not true. The separation of concerns + does exist +| in the context of HTML and CSS (and JS), but not in the way a lot of + people +| seem to believe. + +| The separation of concerns when applied to front-end code is not about +| classes-in-HTML-purely-for-styling-hooks-blurring-the-lines-between-concerns; +| it is about the very fact that we are using different languages for + markup and +| styling at all. + +| Back before CSS was widely adopted, we’d use ``tables`` to lay content + out, and +| ``font`` elements with ``color`` attributes to provide cosmetic + styling. The +| problem here is that HTML was being used to create content and also to + style +| it; there was no way of having one without the other. This was a + complete lack +| of separation of concerns, which was a problem. CSS’ job was to + provide a +| completely new syntax to apply this styling, allowing us to separate + our +| content and style concerns across two technologies. + +Another common argument is that *‘putting classes in your HTML puts +style information in your markup’*. + +| So, in a bid to circumvent this, people adopt selectors that might + look a +| little like this: + +.. code:: css + + body > header:first-of-type > nav > ul > li > a { + } + +| This CSS—presumably to style our site’s main nav—has the usual + problems of +| location dependency, poor Selector Intent, and high specificity, but + it also +| manages to do exactly what *developers* are trying to avoid, only in + the +| opposite direction: **it puts DOM information in your CSS**. + Aggressive +| attempts to avoid putting any style hints or hooks in markup only lead + to +| overloading stylesheets with DOM information. + +| In short: having classes in your markup does not violate the + separation of +| concerns. Classes merely act as an API to link two separate concerns + together. +| The simplest way to separate concerns is to write well formed HTML and + well +| formed CSS, and link to two together with sensible, judicious use of + classes. + +.. _The media object saves hundreds of lines of code: http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code/ +.. _The flag object: http://csswizardry.com/2013/05/the-flag-object/ +.. _Naming UI components in OOCSS: http://csswizardry.com/2014/03/naming-ui-components-in-oocss/ +.. _The single responsibility principle applied to CSS: http://csswizardry.com/2012/04/the-single-responsibility-principle-applied-to-css/ +.. _The open/closed principle applied to CSS: http://csswizardry.com/2012/06/the-open-closed-principle-applied-to-css/ +.. _Writing DRYer vanilla CSS: http://csswizardry.com/2013/07/writing-dryer-vanilla-css/ diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index eedfa940..c8e12fbf 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -1,601 +1,401 @@ Introduction -============ - -CSS is not a pretty language. While it is simple to learn and get started with, -it soon becomes problematic at any reasonable scale. There isn’t much we can do -to change how CSS works, but we can make changes to the way we author and -structure it. - -There are a variety of techniques we must employ in order to satisfy these -goals, and CSS Guidelines is a document of recommendations and approaches that -will help us to do so. - -The first part of this will deal with syntax, formatting and CSS anatomy, the -second part will deal with approach, mind frame and attitude toward writing and -architecting CSS. - - -Meaningful Whitespace -===================== - -Only one style should exist across the entire source of all your code-base. -Always be consistent in your use of whitespace. Use whitespace to improve -readability. - -- Never mix spaces and tabs for indentation. Stick to your choice without fail. (**Preference: tabs**) -- Choose the number of preferred characters used per indentation level. (**Preference: 4 spaces**) - -.. warning:: - -configure your editor to "show invisibles" or to automatically remove end-of-line whitespace. The use of an `EditorConfig <http://editorconfig.org/>`_ file is being used to help maintain the basic whitespace conventions. - - -As well as indentation, we can provide a lot of information through liberal and -judicious use of whitespace between rulesets. We use: - -- One (1) empty line between closely related rulesets. -- Two (2) empty lines between loosely related rulesets. - -For example: - -.. code-block:: scss - - //------------------------------------------------------------------------------ - // #FOO - //------------------------------------------------------------------------------ - - .foo { } - - .foo__bar { } - - - .foo--baz { } - - -There should never be a scenario in which two rulesets do not have an empty line -between them. This would be incorrect: - -.. code-block:: scss - - .foo { } - .foo__bar { } - .foo--baz { } - - - -Multiple Files -============== - -With the meteoric rise of preprocessors of late, more often is the case that -developers are splitting CSS across multiple files. - -Even if not using a preprocessor, it is a good idea to split discrete chunks of -code into their own files, which are concatenated during a build step. - -We follow the ITCSS principles for the organization of our code and as such -everything is broken up into partials. All partials are to be named to reflect -the contained component/module and lead by an underscore(`_`) to prevent self -rendering. - - -Commenting -========== - -**CSS needs more comments.** - -The cognitive overhead of working with CSS is huge. With so much to be aware of, -and so many project-specific nuances to remember, the worst situation most -developers find themselves in is being the-person-who-didn’t-write-this-code. -Remembering your own classes, rules, objects, and helpers is manageable to an -extent, but anyone inheriting CSS barely stands a chance. - -This is why well commented code is extremely important. Take time to describe -components, how they work, their limitations, and the way they are constructed. -Don't leave others in the project guessing as to the purpose of uncommon or -non-obvious code. - -Comment style should be simple and consistent within the code base. - -- Place comments on a new line above their subject. -- Keep line-length to a sensible maximum, e.g., 80 columns. -- Make liberal use of comments to break CSS code into discrete sections. -- Use "sentence case" comments and consistent text indentation. - -As CSS is something of a declarative language that doesn’t really leave much of -a paper-trail, it is often hard to discern—from looking at the CSS alone— - -- whether some CSS relies on other code elsewhere; -- what effect changing some code will have elsewhere; -- where else some CSS might be used; -- what styles something might inherit (intentionally or otherwise); -- what styles something might pass on (intentionally or otherwise); -- where the author intended a piece of CSS to be used. - -This doesn’t even take into account some of CSS’ many quirks—such as various -sates of `overflow` triggering block formatting context, or certain transform -properties triggering hardware acceleration—that make it even more baffling to -developers inheriting projects. - -As a result of CSS not telling its own story very well, it is a language that -really does benefit from being heavily commented. - -As a rule, you should comment anything that isn’t immediately obvious from the -code alone. That is to say, there is no need to tell someone that `color: red;` -will make something red, but if you’re using `overflow: hidden;` to clear -floats—as opposed to clipping an element’s overflow—this is probably something -worth documenting. - -.. warning:: - -Tip: you can configure your editor to provide you with shortcuts to output agreed-upon comment patterns. - -Comment Example: - -.. code-block:: scss - - //------------------------------------------------------------------------------ - // #[LAYER]: PARTIAL NAME - //------------------------------------------------------------------------------ - // #description - // - // This is a description of the PARTIAL - // - //------------------------------------------------------------------------------ - - // - // #settings - - // Layout Variables - $variable: [value] - - // Theme Variables - $variable: [value] - - // - // #scss - - // - // 1. inline comment - // 2. inline comment - // 3. inline comment - // - - [selector] { - [property]: [value]; - [property]: [value]; // [1] - [property]: [value]; // [1] - [property]: [value]; // [2] - [property]: [value]; - [property]: [value]; // [3] - } - - // - // Section Block Comment - //------------------------------------------------------------------------------ - // - // 1. inline comment - // 2. inline comment - // 3. inline comment - // - [selector] { - [property]: [value]; - [property]: [value]; // [1] - [property]: [value]; // [1] - [property]: [value]; // [2] - [property]: [value]; - [property]: [value]; // [3] - } - - - -Low-level ---------- - -Oftentimes we want to comment on specific declarations (i.e. lines) in a -ruleset. To do this we use a kind of reverse footnote. Here is a more complex -comment detailing the larger site headers mentioned above: - -.. code-block:: scss - - // - // 1. Allow us to style box model properties. - // 2. Line different sized buttons up a little nicer. - // 3. Make buttons inherit font styles (often necessary when styling `input`s as - // buttons). - // 4. Reset/normalize some styles. - // 5. Force all button-styled elements to appear clickable. - // 6. Fixes odd inner spacing in IE7. - // 7. Subtract the border size from the padding value so that buttons do not - // grow larger as we add borders. - // 8. Prevent button text from being selectable. - // 9. Prevent deafult browser outline halo - // - .o-btn { - @include type(button); - @include shadow(2); - line-height: unitless($btn-height, map-get(map-get($type-styles, button), font-size)); - text-align: center; // [4] - vertical-align: middle; // [2] - white-space: nowrap; - text-decoration: none; // [4] - background-color: $btn-background-color; - border: none; - border-radius: $btn-border-radius; - outline: none; // [9] - color: $btn-text-color; - position: relative; - display: inline-block; // [1] - overflow: hidden; // [6] - min-width: $btn-min-width; - margin: 0; // [4] - padding: 0 $btn-spacing; // [7] - cursor: pointer; - user-select: none; // [8] - transition: - box-shadow 0.2s $animation-curve-fast-out-linear-in, - background-color 0.2s $default-animation-curve, - color 0.2s $default-animation-curve; - will-change: box-shadow; - } - - -These types of comment allow us to keep all of our documentation in one place -whilst referring to the parts of the ruleset to which they belong. - - -Titling -------- - -Begin every new major section of a CSS project with a title: - -.. code-block:: scss - - //------------------------------------------------------------------------------ - // #SECTION-TITLE - //------------------------------------------------------------------------------ - - .selector { } - - -The title of the section is prefixed with a hash (`#`) symbol to allow us to -perform more targeted searches (e.g. `grep`, etc.): instead of searching for -just `SECTION-TITLE`—which may yield many results—a more scoped search of -`#SECTION-TITLE` should return only the section in question. - -Leave a carriage return between this title and the next line of code (be that a -comment, some Sass, or some CSS). - - -Preprocessor Comments ---------------------- - -With most—if not all—preprocessors, we have the option to write comments that -will not get compiled out into our resulting CSS file. As a rule, use these -comments to speed up and prevent errors in the minification step. - +------------ + +| CSS is not a pretty language. While it is simple to learn and get + started with, +| it soon becomes problematic at any reasonable scale. There isn’t much + we can do +| to change how CSS works, but we can make changes to the way we author + and +| structure it. + +| There are a variety of techniques we must employ in order to satisfy + these +| goals, and CSS Guidelines is a document of recommendations and + approaches that +| will help us to do so. + +| The first part of this will deal with syntax, formatting and CSS + anatomy, the +| second part will deal with approach, mindframe and attitude toward + writing and +| architecting CSS. Syntax and Formatting -===================== +--------------------- -One of the simplest forms of a styleguide is a set of rules regarding syntax and -formatting. Having a standard way of writing (literally writing) CSS means that -code will always look and feel familiar to all members of the team. +| One of the simplest forms of a styleguide is a set of rules regarding + syntax and +| formatting. Having a standard way of writing (literally writing) CSS + means that +| code will always look and feel familiar to all members of the team. -Further, code that looks clean feels clean. It is a much nicer environment to -work in, and prompts other team members to maintain the standard of cleanliness -that they found. Ugly code sets a bad precedent. +| Further, code that looks clean feels clean. It is a much nicer + environment to +| work in, and prompts other team members to maintain the standard of + cleanliness +| that they found. Ugly code sets a bad precedent. -The chosen code format must ensure that code is: easy to read; easy to clearly -comment; minimizes the chance of accidentally introducing errors; and results in -useful diffs and blames. +| The chosen code format must ensure that code is: easy to read; easy to + clearly +| comment; minimizes the chance of accidentally introducing errors; and + results in +| useful diffs and blames. At a very high-level, we want -- Tab (4 space width) indents; -- 80 character wide columns; -- multi-line CSS; -- a meaningful use of comments & whitespace. - +- Tab (4 space width) indents; +- 80 character wide columns; +- multi-line CSS; +- a meaningful use of comments & whitespace. Anatomy of a Ruleset --------------------- +~~~~~~~~~~~~~~~~~~~~ -Before we discuss how we write out our rulesets, let’s first familiarize ourselves with the relevant terminology: +| Before we discuss how we write out our rulesets, let’s first + familiarize +| ourselves with the relevant terminology: The following is a ``[ruleset]`` -.. code-block:: text - - [selector], - [selector] { - [property]: [value]; | - [property]: [value]; | <- [declaration-block] - [property]: [value]; | - [<--declaration--->] - } - - - -Formatting ---------- - -- Use one discrete selector per line in multi-selector rulesets. -- The opening brace (``{``) should be on the same line as our last selector. -- Include a single space before the opening brace (``{``). -- Include properties and values on the same line. -- Include one declaration per line in a declaration block. -- Use one level of indentation for each declaration. -- Include a single space after the colon (``:``) of a declaration. -- Use lowercase hex values, e.g., #abc123. -- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""``. -- Always quote attribute values in selectors, e.g., ``input[type="checkbox"]``. -- Avoid specifying units for zero-values, e.g., ``margin: 0``. -- Always use leading zeros, e.g, ``font-size: 0.875rem`` -- Include a space after each comma(``,``) in comma-separated property or function values. -- Include a semi-colon(``;``) at the end of every declaration including the last in a declaration block. -- Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line. -- Separate each ruleset by a blank line. +.. code:: css -Example: + [selector], + [selector] { + [property]: [value]; | + [property]: [value]; | <- [declaration-block] + [property]: [value]; | + [<--declaration--->] + } -.. code-block:: scss +Formating +~~~~~~~~~ + +- Use one discrete selector per line in multi-selector rulesets. +- The opening brace (``{``) should be on the same line as our last + selector. +- Include a single space before the opening brace (``{``). +- Include properties and values on the same line. +- Include one declaration per line in a declaration block. +- Use one level of indentation for each declaration. +- Include a single space after the colon (``:``) of a declaration. +- Use lowercase hex values, e.g., #abc123. +- Use quotes consistently. **Preference double quotes**, e.g., + ``content: ""``. +- Always quote attribute values in selectors, e.g., + ``input[type="checkbox"]``. +- Avoid specifying units for zero-values, e.g., ``margin: 0``. +- Always use leading zeros, e.g, ``font-size: 0.875rem`` +- Include a space after each comma(\ ``,``) in comma-separated property + or function values. +- Include a semi-colon(\ ``;``) at the end of every declaration + including the last in a declaration block. +- Place the closing brace (``}``) of a ruleset in the same column as + the first character of the ruleset, on its own line. +- Separate each ruleset by a blank line. - .selector-1, - .selector-2, - .selector-3[type="text"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - display: block; - padding: 0; - font-family: helvetica, arial, sans-serif; - color: #333333; - background: #ffffff; - background: linear-gradient(#ffffff, rgba(0, 0, 0, 0.8)); - } +Example: - .selector-a, - .selector-b { - padding: 10px; - } +.. code:: scss + + .selector-1, + .selector-2, + .selector-3[type="text"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + padding: 0; + font-family: helvetica, arial, sans-serif; + color: #333333; + background: #ffffff; + background: linear-gradient(#ffffff, rgba(0, 0, 0, 0.8)); + } + .selector-a, + .selector-b { + padding: 10px; + } -This format seems to be the largely universal standard (except for variations in -indentation). +| This format seems to be the largely universal standard (except for + variations in +| indentation). As such, the following would be incorrect: -.. code-block:: scss - - .foo, .foo-bar, .baz - { - display:block; - background-color:green; - color:red } +.. code:: scss + .foo, .foo-bar, .baz + { + display:block; + background-color:green; + color:red } Problems here include -- 2 spaces instead of tabs (4 space width). -- selectors on the same line. -- the opening brace (``{``) on its own line. -- the closing brace (``}``) does not sit on its own line. -- the last semi-colon (``;``) is missing. -- no spaces after colons (``:``). - +- 2 spaces instead of tabs (4 space width). +- selectors on the same line. +- the opening brace (``{``) on its own line. +- the closing brace (``}``) does not sit on its own line. +- the last semi-colon (``;``) is missing. +- no spaces after colons (``:``). Multi-line CSS --------------- - -CSS should be written across multiple lines, except in very specific -circumstances. There are a number of benefits to this: +~~~~~~~~~~~~~~ -- A reduced chance of merge conflicts, because each piece of functionality exists on its own line. -- More ‘truthful’ and reliable ``diffs``, because one line only ever carries one change. +| CSS should be written across multiple lines, except in very specific +| circumstances. There are a number of benefits to this: -Exceptions to this rule should be fairly apparent, such as similar rulesets -that only carry one declaration each, for example: +- A reduced chance of merge conflicts, because each piece of + functionality exists on its own line. +- More ‘truthful’ and reliable ``diffs``, because one line only ever + carries one change. -.. code-block:: css +| Exceptions to this rule should be fairly apparent, such as similar + rulesets +| that only carry one declaration each, for example: - .icon { - display: inline-block; - width: 16px; - height: 16px; - background-image: url(/img/sprite.svg); - } +.. code:: css - .icon-home { background-position: 0 0; } - .icon-person { background-position: -16px 0; } - .icon-files { background-position: 0 -16px; } - .icon-settings { background-position: -16px -16px; } + .icon { + display: inline-block; + width: 16px; + height: 16px; + background-image: url(/img/sprite.svg); + } + .icon-home { background-position: 0 0; } + .icon-person { background-position: -16px 0; } + .icon-files { background-position: 0 -16px; } + .icon-settings { background-position: -16px -16px; } These types of ruleset benefit from being single-lined because -- they still conform to the one-reason-to-change-per-line rule; -- they share enough similarities that they don’t need to be read as thoroughly as other rulesets—there is more benefit in being able to scan their selectors, which are of more interest to us in these cases. - +- they still conform to the one-reason-to-change-per-line rule; +- they share enough similarities that they don’t need to be read as + thoroughly as other rulesets—there is more benefit in being able to + scan their selectors, which are of more interest to us in these + cases. Declaration order ------------------ +~~~~~~~~~~~~~~~~~ -declarations are to be consistently ordered by related property declarations -following the order +| declarations are to be consistently ordered by related property + declarations +| following the order -1. Typographic -2. Visual -3. Positioning -4. Box model -5. Misc +#. Typographic +#. Visual +#. Positioning +#. Box model +#. Misc Example: -.. code-block:: scss - - .declaration-order { - /* Typography */ - font: normal 13px "Helvetica Neue", sans-serif; - line-height: 1.5; - text-align: center; - - /* Visual */ - background-color: #f5f5f5; - border: 1px solid #e5e5e5; - border-radius: 3px; - color: #333333; - - /* Positioning */ - position: absolute; - z-index: 100; - top: 0; - right: 0; - bottom: 0; - left: 0; - - /* Box-model */ - display: block; - float: right; - width: 100px; - height: 100px; - margin: 0; - padding: 8px; - - /* Misc */ - content: "-"; - } - - +.. code:: scss + + .declaration-order { + /* Typography */ + font: normal 13px "Helvetica Neue", sans-serif; + line-height: 1.5; + text-align: center; + + /* Visual */ + background-color: #f5f5f5; + border: 1px solid #e5e5e5; + border-radius: 3px; + color: #333333; + + /* Positioning */ + position: absolute; + z-index: 100; + top: 0; + right: 0; + bottom: 0; + left: 0; + + /* Box-model */ + display: block; + float: right; + width: 100px; + height: 100px; + margin: 0; + padding: 8px; + + /* Misc */ + content: "-"; + } Proper Use of units -------------------- +~~~~~~~~~~~~~~~~~~~ -CSS allows for the use of several different unit types. As such it can get -confusing when using more than one type of unit through out the project. For -that reason its beneficial to stick to a stick set of rules for what unit types -are to be used for certain selectors. +| CSS allows for the use of several different unit types. As such it can + get +| confusing when using more than one type of unit through out the + project. For +| that reason its beneficial to stick to a stick set of rules for what + unit types +| are to be used for certain selectors. -Furthermore there are certain reasons to use or avoid using specific units in -certain places. +| Furthermore there are certain reasons to use or avoid using specific + units in +| certain places. EM -++ - -The 'em' unit. This is a very problematic unit which reeks havoc on countless -projects due to the way its calculated. As such this unit type must be avoid -except for very very minimal use cases. We prevent the use of ``em`` except for -``letter-spaceing`` & ``word-spacing``. It is also used for icon sizing but that is -an edge case. +^^ + +| The ‘em’ unit. This is a very problematic unit which reeks havoc on + countless +| projects due to the way its calculated. As such this unit type must be + avoid +| except for very very minimal use cases. We prevent the use of ``em`` + except for +| ``letter-spaceing`` & ``word-spacing``. It is also used for icon + sizing but that is +| an edge case. Line-heights -++++++++++++ +^^^^^^^^^^^^ -All line-heights are to be specified as unitless in order to prevent in proper -inheritance. By nature when using units with line-heights the children inherit -by default. This can lead to unwanted effects and bloated code. A ``sass`` -function called ``unitless`` is provided which will convert px values for -convenience, but for clarity the math is simply +| All line-heights are to be specified as ``unitless`` in order to + prevent in proper +| inheritance. By nature when using units with line-heights the children + inherit +| by default. This can lead to unwanted effects and bloated code. A + ``sass`` +| function called ``unitless`` is provided which will convert px values + for +| convenience, but for clarity the math is simply -.. code-block:: scss - - line-height: (desired px value) / (current elements font-size) +.. code:: scss + line-height: (desired px value) / (current elements font-size) Font-size -+++++++++ +^^^^^^^^^ -All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. All px -values will be converted to ``rem`` during the build process as ``rem`` provide for -control in responsive situations. +| All ``font-size`` should be specified either in ``px`` or ``%`` in + small cases. All px +| values will be converted to ``rem`` during the build process as + ``rem`` provide for +| control in responsive situations. Margins & Paddings -++++++++++++++++++ +^^^^^^^^^^^^^^^^^^ -All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` All -px values will be converted to ``rem`` during the build process as `rem` provide -for control in responsive situations. +| All ``margin`` & ``padding`` should be specified in ``px`` values or + ``%``. All ``px`` All +| px values will be converted to ``rem`` during the build process as + ``rem`` provide +| for control in responsive situations. PX -++ -All ``px`` will be whole numbers. Browsers do not render ``px`` in fractional values -despite what you browser may say it is. Only calculated values will display as -fractional ``px``. For clarification a calculated value would be units like ``rem``, -``em``, ``%``, & even ``unitless`` as is the case with line-heights. - -Dimensions -++++++++++ - -All dimensional values ``width``, ``min-width``, ``height``, & ``min-height`` should be -specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, but they are still -on the fringe of browser acceptance, as such fallbacks in ``px`` or ``%`` are -required. These values will remain as px if specified. This is done as ``height`` -is more effectively and appropriately controlled via the ``line-height`` property, -and ``width`` is better specified using the objects box-model via ``padding`` unless -its fluid in which ``100%`` can be specified or u can also use -``left: 0; right: 0;`` +^^ +| All ``px`` will be whole numbers. Browsers do not render ``px`` in + fractional values +| despite what you browser may say it is. Only calculated values will + display as +| fractional ``px``. For clarification a calculated value would be units + like ``rem``, +| ``em``, ``%``, & even ``unitless`` as is the case with line-heights. +Dimensions +^^^^^^^^^^ + +| All dimensional values ``width``, ``min-width``, ``height``, & + ``min-height`` should be +| specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, + but they are still +| on the fringe of browser acceptance, as such fallbacks in ``px`` or + ``%`` are +| required. These values will remain as px if specified. This is done as + ``height`` +| is more effectively and appropriately controlled via the + ``line-height`` property, +| and ``width`` is better specified using the objects box-model via + ``padding`` unless +| its fluid in which ``100%`` can be specified or u can also use +| ``left: 0; right: 0;`` Indenting Sass -++++++++++++++ +^^^^^^^^^^^^^^ Sass provides nesting functionality. That is to say, by writing this: -.. code-block:: css +.. code:: css - .foo { - color: red; + .foo { + color: red; - .bar { - color: blue; + .bar { + color: blue; + } } - } - …we will be left with this compiled CSS: -.. code-block:: css +.. code:: css - .foo { color: red; } - .foo .bar { color: blue; } + .foo { color: red; } + .foo .bar { color: blue; } +| When indenting Sass, we stick to the same two indentation, and we also + leave a +| blank line before and after the nested ruleset. -When indenting Sass, we stick to the same two indentation, and we also leave a -blank line before and after the nested ruleset. +**N.B.** Nesting in Sass should be avoided in most cases. See the +Specificity section for more data +Enforcing standardisation +~~~~~~~~~~~~~~~~~~~~~~~~~ -**N.B.** Nesting in Sass should be avoided in most cases. See `Specificity`_ for more details. +Our project makes use of several tools to lint and to keep us to the +standards. +1. `stylelint.io`_ +^^^^^^^^^^^^^^^^^^ -Enforcing standardization -------------------------- +.. note:: -Our project makes use of several tools to lint and to keep us to the standards. +This is used to provide detailed linting for our standards via the +``.stlyelintrc`` file in the root of the project. + +2. `postcss-sorting`_ +^^^^^^^^^^^^^^^^^^^^^ -1. `stylelint.io <http://www.stylelint.io>`_ -++++++++++++++++++++++++++++++++++++++++++++ .. note:: -This is used to provide detailed linting for our standards via the ``.stlyelintrc`` file in the root of the project. +This is used to provide automatic sorting to our declaration order +via the ``.postcss-sorting.json`` file in the root of the project. + +3. `postcss-pxtorem`_ +^^^^^^^^^^^^^^^^^^^^^ -2. `postcss-sorting <https://github.com/hudochenkov/postcss-sorting>`_ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. note:: -This is used to provide automatic sorting to our declaration order via the ``.postcss-sorting.json`` file in the root of the project. +This is used to ensure the proper units are consistently used +throughout the project during the build process via the ``gulp`` as well +as on save in your editor. + +4. `stylefmt`_ +^^^^^^^^^^^^^^ -3. `postcss-pxtorem <https://github.com/cuth/postcss-pxtorem>`_ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. note:: -This is used to ensure the proper units are consistently used throughout the project during the build process via the ``gulp`` as well as on save in your editor. +This is used to help automatically re-format your code to the +standards on the fly during the build process via ``gulp`` as well as on +save in your editor. -4. `stylefmt <https://github.com/morishitter/stylefmt>`_ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. note:: -This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. - -.. warning:: +As a **NOTE** our editor of choice is `ATOM`_ which provides usefull +plugins to make use of these tools. Checkout the `Editor Setup`_ section +of the docs for more information -As a **NOTE** our editor of choice is `ATOM <http://www.atom.io>`_ which provides useful plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information +.. _stylelint.io: http://www.stylelint.io +.. _postcss-sorting: https://github.com/hudochenkov/postcss-sorting +.. _postcss-pxtorem: https://github.com/cuth/postcss-pxtorem +.. _stylefmt: https://github.com/morishitter/stylefmt +.. _ATOM: http://www.atom.io +.. _Editor Setup: /editor-setup diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst index 874f7079..09871a7a 100644 --- a/development/development/css_naming.rst +++ b/development/development/css_naming.rst @@ -1,209 +1,283 @@ Naming Conventions -================== +------------------ -Naming conventions in CSS are hugely useful in making your code more strict, -more transparent, and more informative. +| Naming conventions in CSS are hugely useful in making your code more + strict, +| more transparent, and more informative. A good naming convention will tell you and your team -- what type of thing a class does; -- where a class can be used; -- what (else) a class might be related to. +- what type of thing a class does; +- where a class can be used; +- what (else) a class might be related to. The naming convention we follow are as follows -- Hyphen (`-`) delimited strings. -- Layer namespacing -- A variation on BEM-like naming for action modifiers +- Hyphen (``-``) delimited strings. +- Layer namespacing +- A variation on BEM-like naming for action modifiers -It’s worth noting that not all the naming convention are normally useful -in the CSS-side of development; they really come into their own when viewed in -HTML. +| It’s worth noting that not all the naming convention are normally + useful +| in the CSS-side of development; they really come into their own when + viewed in +| HTML. Hyphen Delimited ----------------- +~~~~~~~~~~~~~~~~ -All strings in classes are delimited with a hyphen (`-`), like so: +All strings in classes are delimited with a hyphen (``-``), like so: -.. code-block:: css +.. code:: css - .page-head { } + .page-head { } - .sub-content { } + .sub-content { } +| Camel case and underscores are not used for regular classes; the + following are +| incorrect: -Camel case and underscores are not used for regular classes; the following are -incorrect: +.. code:: css -.. code-block:: css - - .pageHead { } - - .sub_content { } + .pageHead { } + .sub_content { } Modified BEM-like Naming ------------------------- - -For larger, more interrelated pieces of UI that require a number of classes, we -use a modified BEM-like naming convention. - -BEM, meaning Block, Element, Modifier, is a front-end methodology coined by -developers working at Yandex. Whilst BEM is a complete methodology, here we are -only concerned with its naming convention. Further, the naming convention here -only is BEM-like; the principles are exactly the same, but the actual syntax -differs. +~~~~~~~~~~~~~~~~~~~~~~~~ + +| For larger, more interrelated pieces of UI that require a number of + classes, we +| use a modified BEM-like naming convention. + +| BEM, meaning Block, Element, Modifier, is a front-end methodology + coined by +| developers working at Yandex. Whilst BEM is a complete methodology, + here we are +| only concerned with its naming convention. Further, the naming + convention here +| only is BEM-like; the principles are exactly the same, but the actual + syntax +| differs. BEM splits components’ classes into three groups: -- Block: The sole root of the component. -- Element: A component part of the Block. -- Modifier: A variant or extension of the Block. +- Block: The sole root of the component. +- Element: A component part of the Block. +- Modifier: A variant or extension of the Block. To take an analogy (note, not an example): -.. code-block:: css +.. code:: css - .dropdown { } - .dropdown-item { } - .dropdown--active { } + .dropdown { } + .dropdown-item { } + .dropdown--active { } +| Elements are delimited with two (hyphens (``-``), and Modifiers are + delimited by +| two (2) hyphens (``--``). -Elements are delimited with two (hyphens (`-`), and Modifiers are delimited by -two (2) hyphens (`--`). +| Here we can see that ``.dropdown {}`` is the Block; it is the sole + root of a +| discrete entity. ``.dropdown-item {}`` is an Element; it is a smaller + part of the +| ``.dropdown {}`` Block. Finally, ``.dropdown--active {}`` is a + Modifier; it is a +| specific variant of the ``.dropdown {}`` Block. -Here we can see that `.dropdown {}` is the Block; it is the sole root of a -discrete entity. `.dropdown-item {}` is an Element; it is a smaller part of the -`.dropdown {}` Block. Finally, `.dropdown--active {}` is a Modifier; it is a -specific variant of the `.dropdown {}` Block. +Starting Context +^^^^^^^^^^^^^^^^ -#### Starting Context +| Your Block context starts at the most logical, self-contained, + discrete +| location. To continue with our dropdown-based analogy, we’d not have a + class +| like ``.header-dropdown {}``, as the header is another, much higher + context. We’d +| probably have separate Blocks, like so: -Your Block context starts at the most logical, self-contained, discrete -location. To continue with our dropdown-based analogy, we’d not have a class -like `.header-dropdown {}`, as the header is another, much higher context. We’d -probably have separate Blocks, like so: +.. code:: css -.. code-block:: css + .header { } - .header { } + .header-nav { } - .header-nav { } + .dropdown { } - .dropdown { } + .dropdown-item { } - .dropdown-item { } +| If we did want to denote a ``.dropdown {}`` inside a ``.header {}``, + it is more +| correct to use a selector like ``.header .dropdown {}`` which bridges + two Blocks +| than it is to increase the scope of existing Blocks and Elements. +| A more realistic example of properly scoped blocks might look + something like +| this, where each chunk of code represents its own Block: -If we did want to denote a `.dropdown {}` inside a `.header {}`, it is more -correct to use a selector like `.header .dropdown {}` which bridges two Blocks -than it is to increase the scope of existing Blocks and Elements. +.. code:: css -A more realistic example of properly scoped blocks might look something like -this, where each chunk of code represents its own Block: + .page { } -.. code-block:: css - .page { } + .content { } - .content { } - - - .footer { } - - .footer-copyright { } + .footer { } + .footer-copyright { } Incorrect notation for this would be: -.. code-block:: css - - .page { } +.. code:: css - .page-content { } + .page { } - .page-footer { } + .page-content { } - .page-copyright { } + .page-footer { } + .page-copyright { } -It is important to know when BEM scope starts and stops. As a rule, BEM applies -to self-contained, discrete parts of the UI. +| It is important to know when BEM scope starts and stops. As a rule, + BEM applies +| to self-contained, discrete parts of the UI. More Layers -+++++++++++ - -If we were to add another Element—called, let’s say, `.dropdown-link {}`—to -this `.dropdown {}` component, we would not need to step through every layer of -the DOM. That is to say, the correct notation would be `.dropdown-link {}`, and -not `.dropdown-item-link {}`. Your classes do not reflect the full paper-trail -of the DOM. - - -### Layer Namespacing - -There are a number of common problems when working with CSS at scale, but the -major two that namespacing aims to solve are clarity and confidence: - -- **Clarity:** How much information can we glean from the smallest possible source? Is our code self-documenting? Can we make safe assumptions from a single context? How much do we have to rely on external or supplementary information in order to learn about a system? -- **Confidence:** Do we have enough knowledge about a system to be able to safely interface with it? Do we know enough about our code to be able to confidently make changes? Do we have a way of knowing the potential side effects of making a change? Do we have a way of knowing what we might be able to remove? - -This gets further complicated when dealing with -[ITCSS](https://www.youtube.com/watch?v=1OKZOV-iLj4). Knowing what layer a -class is coming from is not always apparent. To combat this and provide complete -transparency we use layer based namespacing. - -In no particular order, here are the individual namespaces and a brief -description. We’ll look at each in more detail in a moment, but the following -list should acquaint you. - -- `o-`: Signify that something is an Object, and that it may be used in any number of unrelated contexts to the one you can currently see it in. Making modifications to these types of class could potentially have knock-on effects in a lot of other unrelated places. Tread carefully. -- `c-`: Signify that something is a Component. This is a concrete, implementation-specific piece of UI. All of the changes you make to its styles should be detectable in the context you’re currently looking at. Modifying these styles should be safe and have no side effects. -- `u-`: Signify that this class is a Utility class. It has a very specific role (often providing only one declaration) and should not be bound onto or changed. It can be reused and is not tied to any specific piece of UI. You will probably recognize this namespace from libraries and methodologies like `SUITcss <https://suitcss.github.io/>`_. -- `t-`: Signify that a class is responsible for adding a Theme to a view. It lets us know that UI Components’ current cosmetic appearance may be due to the presence of a theme. Vastly improves templating for large projects -- `s-`: Signify that a class creates a new styling context or Scope. Similar to a Theme, but not necessarily cosmetic, these should be used sparingly—they can be open to abuse and lead to poor CSS if not used wisely. -- `is-`, `has-`: Signify that the piece of UI in question is currently styled a certain way because of a state or condition. This stateful namespace is gorgeous, and comes from `SMACSS <https://smacss.com/>`_. It tells us that the DOM currently has a temporary, optional, or short-lived style applied to it due to a certain state being invoked. -- `_`: Signify that this class is the worst of the worst—a hack! Sometimes, although incredibly rarely, we need to add a class in our markup in order to force something to work. If we do this, we need to let others know that this class is less than ideal, and hopefully temporary (i.e. do not bind onto this). -- `js`-: Signify that this piece of the DOM has some behavior acting upon it, and that JavaScript binds onto it to provide that behavior. If you’re not a developer working with JavaScript, leave these well alone. - -Even from this short list alone, we can see just how much more information we -can communicate to developers simply by placing a character or two at the front -of our existing classes. - - -**Further Reading** - -- `UI Selector Namspacing <https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/>`_ - +^^^^^^^^^^^ + +| If we were to add another Element—called, let’s say, + ``.dropdown-link {}``—to +| this ``.dropdown {}`` component, we would not need to step through + every layer of +| the DOM. That is to say, the correct notation would be + ``.dropdown-link {}``, and +| not ``.dropdown-item-link {}``. Your classes do not reflect the full + paper-trail +| of the DOM. + +Layer Namespacing +~~~~~~~~~~~~~~~~~ + +| There are a number of common problems when working with CSS at scale, + but the +| major two that namespacing aims to solve are clarity and confidence: + +- **Clarity:** How much information can we glean from the smallest + possible source? Is our code self-documenting? Can we make safe + assumptions from a single context? How much do we have to rely on + external or supplementary information in order to learn about a + system? +- **Confidence:** Do we have enough knowledge about a system to be able + to safely interface with it? Do we know enough about our code to be + able to confidently make changes? Do we have a way of knowing the + potential side effects of making a change? Do we have a way of + knowing what we might be able to remove? + +| This gets further complicated when dealing with +| `ITCSS`_. Knowing what layer a +| class is coming from is not always apparent. To combat this and + provide complete +| transparency we use layer based namespacing. + +| In no particular order, here are the individual namespaces and a brief +| description. We’ll look at each in more detail in a moment, but the + following +| list should acquaint you. + +- ``o-``: Signify that something is an Object, and that it may be used + in any number of unrelated contexts to the one you can currently see + it in. Making modifications to these types of class could potentially + have knock-on effects in a lot of other unrelated places. Tread + carefully. +- ``c-``: Signify that something is a Component. This is a concrete, + implementation-specific piece of UI. All of the changes you make to + its styles should be detectable in the context you’re currently + looking at. Modifying these styles should be safe and have no side + effects. +- ``u-``: Signify that this class is a Utility class. It has a very + specific role (often providing only one declaration) and should not + be bound onto or changed. It can be reused and is not tied to any + specific piece of UI. You will probably recognize this namespace from + libraries and methodologies like `SUITcss`_. +- ``t-``: Signify that a class is responsible for adding a Theme to a + view. It lets us know that UI Components’ current cosmetic appearance + may be due to the presence of a theme. Vastly improves templating for + large projects +- ``s-``: Signify that a class creates a new styling context or Scope. + Similar to a Theme, but not necessarily cosmetic, these should be + used sparingly—they can be open to abuse and lead to poor CSS if not + used wisely. +- ``is-``, ``has-``: Signify that the piece of UI in question is + currently styled a certain way because of a state or condition. This + stateful namespace is gorgeous, and comes from `SMACSS`_. It tells us + that the DOM currently has a temporary, optional, or short-lived + style applied to it due to a certain state being invoked. +- ``_``: Signify that this class is the worst of the worst—a hack! + Sometimes, although incredibly rarely, we need to add a class in our + markup in order to force something to work. If we do this, we need to + let others know that this class is less than ideal, and hopefully + temporary (i.e. do not bind onto this). +- ``js``-: Signify that this piece of the DOM has some behavior acting + upon it, and that JavaScript binds onto it to provide that behavior. + If you’re not a developer working with JavaScript, leave these well + alone. + +| Even from this short list alone, we can see just how much more + information we +| can communicate to developers simply by placing a character or two at + the front +| of our existing classes. + +Further Reading +''''''''''''''' + + - `UI Selector Namspacing`_ JavaScript Hooks -++++++++++++++++ - -As a rule, it is unwise to bind your CSS and your JS onto the same class in -your HTML. This is because doing so means you can’t have (or remove) one -without (removing) the other. It is much cleaner, much more transparent, and -much more maintainable to bind your JS onto specific classes. - -I have known occasions before when trying to refactor some CSS has unwittingly -removed JS functionality because the two were tied to each other—it was -impossible to have one without the other. - -Typically, these are classes that are prepended with `js-`, for example: - -.. code-block:: html - - <input type="submit" class="btn js-btn" value="Follow" /> - - -This means that we can have an element elsewhere which can carry with style of -`.btn {}`, but without the behaviour of `.js-btn`. - -`data-*` Attributes -+++++++++++++++++++ - -A common practice is to use `data-*` attributes as JS hooks, but this is -incorrect. `data-*` attributes, as per the spec, are used to store custom -data private to the page or application'* (emphasis Harry Roberts). `data-*` -attributes are designed to store data, not be bound to. +~~~~~~~~~~~~~~~~ + +| As a rule, it is unwise to bind your CSS and your JS onto the same + class in +| your HTML. This is because doing so means you can’t have (or remove) + one +| without (removing) the other. It is much cleaner, much more + transparent, and +| much more maintainable to bind your JS onto specific classes. + +| I have known occasions before when trying to refactor some CSS has + unwittingly +| removed JS functionality because the two were tied to each other—it + was +| impossible to have one without the other. + +Typically, these are classes that are prepended with ``js-``, for + example: + +.. code:: html + + <input type="submit" class="btn js-btn" value="Follow" /> + +| This means that we can have an element elsewhere which can carry with + style of +| ``.btn {}``, but without the behavior of ``.js-btn``. + +``data-*`` Attributes +^^^^^^^^^^^^^^^^^^^^^ + +| A common practice is to use ``data-*`` attributes as JS hooks, but + this is +| incorrect. ``data-*`` attributes, as per the spec, are used to store + custom +| data private to the page or application’\* (emphasis Harry Roberts). + ``data-*`` +| attributes are designed to store data, not be bound to. + +.. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 +.. _SUITcss: https://suitcss.github.io/ +.. _SMACSS: https://smacss.com/ +.. _UI Selector Namspacing: https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/ diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst index c0cff7e3..3abe1670 100644 --- a/development/development/css_selectors.rst +++ b/development/development/css_selectors.rst @@ -1,370 +1,475 @@ CSS Selectors -============= +------------- -Perhaps somewhat surprisingly, one of the most fundamental, critical aspects of -writing maintainable and scalable CSS is selectors. Their specificity, their -portability, and their reusability all have a direct impact on the mileage we -will get out of our CSS, and the headaches it might bring us. +| Perhaps somewhat surprisingly, one of the most fundamental, critical + aspects of +| writing maintainable and scalable CSS is selectors. Their specificity, + their +| portability, and their reusability all have a direct impact on the + mileage we +| will get out of our CSS, and the headaches it might bring us. Selector Intent ---------------- - -It is important when writing CSS that we scope our selectors correctly, and that -we’re selecting the right things for the right reasons. Selector Intent is the -process of deciding and defining what you want to style and how you will go -about selecting it. For example, if you are wanting to style your website’s main -navigation menu, a selector like this would be incredibly unwise: - -.. code-block:: css - - header ul { } - - -This selector’s intent is to style any `ul` inside any `header` element, whereas -our intent was to style the site’s main navigation. This is poor Selector -Intent: you can have any number of `header` elements on a page, and they in -turn can house any number of `ul`, so a selector like this runs the risk of -applying very specific styling to a very wide number of elements. This will -result in having to write more CSS to undo the greedy nature of such a selector. +~~~~~~~~~~~~~~~ + +| It is important when writing CSS that we scope our selectors + correctly, and that +| we’re selecting the right things for the right reasons. Selector + Intent is the +| process of deciding and defining what you want to style and how you + will go +| about selecting it. For example, if you are wanting to style your + website’s main +| navigation menu, a selector like this would be incredibly unwise: + +.. code:: css + + header ul { } + +| This selector’s intent is to style any ``ul`` inside any ``header`` + element, whereas +| our intent was to style the site’s main navigation. This is poor + Selector +| Intent: you can have any number of ``header`` elements on a page, and + they in +| turn can house any number of ``uls``, so a selector like this runs the + risk of +| applying very specific styling to a very wide number of elements. This + will +| result in having to write more CSS to undo the greedy nature of such a + selector. A better approach would be a selector like: -.. code-block:: css - - .site-nav { } +.. code:: css + .site-nav { } -An unambiguous, explicit selector with good Selector Intent. We are explicitly -selecting the right thing for exactly the right reason. +| An unambiguous, explicit selector with good Selector Intent. We are + explicitly +| selecting the right thing for exactly the right reason. -Poor Selector Intent is one of the biggest reasons for headaches on CSS -projects. Writing rules that are far too greedy—and that apply very specific -treatments via very far reaching selectors—causes unexpected side effects and -leads to very tangled stylesheets, with selectors overstepping their intentions -and impacting and interfering with otherwise unrelated rulesets. +| Poor Selector Intent is one of the biggest reasons for headaches on + CSS +| projects. Writing rules that are far too greedy—and that apply very + specific +| treatments via very far reaching selectors—causes unexpected side + effects and +| leads to very tangled stylesheets, with selectors overstepping their + intentions +| and impacting and interfering with otherwise unrelated rulesets. -CSS cannot be encapsulated, it is inherently leaky, but we can mitigate some of -these effects by not writing such globally-operating selectors: **your selectors -should be as explicit and well reasoned as your reason for wanting to select -something.** +| CSS cannot be encapsulated, it is inherently leaky, but we can + mitigate some of +| these effects by not writing such globally-operating selectors: **your + selectors should be as explicit and well reasoned as your reason for + wanting to select something.** Reusability ------------ - -With a move toward a more component-based approach to constructing UIs, the idea -of reusability is paramount. We want the option to be able to move, recycle, -duplicate, and syndicate components across our projects. - -To this end, we make heavy use of classes. IDs, as well as being hugely -over-specific, cannot be used more than once on any given page, whereas classes -can be reused an infinite amount of times. Everything you choose, from the type -of selector to its name, should lend itself toward being reused. +~~~~~~~~~~~ + +| With a move toward a more component-based approach to constructing + UIs, the idea +| of reusability is paramount. We want the option to be able to move, + recycle, +| duplicate, and syndicate components across our projects. + +| To this end, we make heavy use of classes. IDs, as well as being + hugely +| over-specific, cannot be used more than once on any given page, + whereas classes +| can be reused an infinite amount of times. Everything you choose, from + the type +| of selector to its name, should lend itself toward being reused. Location Independence ---------------------- - -Given the ever-changing nature of most UI projects, and the move to more -component-based architectures, it is in our interests not to style things based -on where they are, but on what they are. That is to say, our components’ styling -should not be reliant upon where we place them—they should remain entirely -location independent. - -Let’s take an example of a call-to-action button that we have chosen to style -via the following selector: - -.. code-block:: css - - .promo a { } - - -Not only does this have poor Selector Intent—it will greedily style any and -every link inside of a `.promo` to look like a button—it is also pretty wasteful -as a result of being so locationally dependent: we can’t reuse that button with -its correct styling outside of `.promo` because it is explicitly tied to that -location. A far better selector would have been: - -.. code-block:: css - - .btn { } - - -This single class can be reused anywhere outside of `.promo` and will always -carry its correct styling. As a result of a better selector, this piece of UI is -more portable, more recyclable, doesn’t have any dependencies, and has much -better Selector Intent. **A component shouldn’t have to live in a certain place -to look a certain way.** +~~~~~~~~~~~~~~~~~~~~~ + +| Given the ever-changing nature of most UI projects, and the move to + more +| component-based architectures, it is in our interests not to style + things based +| on where they are, but on what they are. That is to say, our + components’ styling +| should not be reliant upon where we place them—they should remain + entirely +| location independent. + +| Let’s take an example of a call-to-action button that we have chosen + to style +| via the following selector: + +.. code:: css + + .promo a { } + +| Not only does this have poor Selector Intent—it will greedily style + any and +| every link inside of a ``.promo`` to look like a button—it is also + pretty wasteful +| as a result of being so locationally dependent: we can’t reuse that + button with +| its correct styling outside of ``.promo`` because it is explicitly + tied to that +| location. A far better selector would have been: + +.. code:: css + + .btn { } + +| This single class can be reused anywhere outside of ``.promo`` and + will always +| carry its correct styling. As a result of a better selector, this + piece of UI is +| more portable, more recyclable, doesn’t have any dependencies, and has + much +| better Selector Intent. **A component shouldn’t have to live in a + certain place + to look a certain way.** Portability ------------ - -Reducing, or, ideally, removing, location dependence means that we can move -components around our markup more freely, but how about improving our ability to -move classes around components? On a much lower level, there are changes we can -make to our selectors that make the selectors themselves—as opposed to the -components they create—more portable. Take the following example: - -.. code-block:: css - - input.btn { } - - -This is a _qualified_ selector; the leading `input` ties this ruleset to only -being able to work on `input` elements. By omitting this qualification, we allow -ourselves to reuse the `.btn` class on any element we choose, like an `a`, for -example, or a `button`. - -Qualified selectors do not lend themselves well to being reused, and every -selector we write should be authored with reuse in mind. - -Of course, there are times when you may want to legitimately qualify a -selector—you might need to apply some very specific styling to a particular -element when it carries a certain class, for example: - -.. code-block:: css - - /** - * Embolden and colour any element with a class of `.error`. - */ - .error { - color: red; - font-weight: bold; - } - - /** - * If the element is a `div`, also give it some box-like styling. - */ - div.error { - padding: 10px; - border: 1px solid; - } - - -This is one example where a qualified selector might be justifiable, but I would -still recommend an approach more like: - -.. code-block:: css - - /** - * Text-level errors. - */ - .error-text { - color: red; - font-weight: bold; - } - - /** - * Elements that contain errors. - */ - .error-box { - padding: 10px; - border: 1px solid; - } - - -This means that we can apply `.error-box` to any element, and not just a -`div`—it is more reusable than a qualified selector. +~~~~~~~~~~~ + +| Reducing, or, ideally, removing, location dependence means that we can + move +| components around our markup more freely, but how about improving our + ability to +| move classes around components? On a much lower level, there are + changes we can +| make to our selectors that make the selectors themselves—as opposed to + the +| components they create—more portable. Take the following example: + +.. code:: css + + input.btn { } + +| This is a *qualified* selector; the leading ``input`` ties this + ruleset to only +| being able to work on ``input`` elements. By omitting this + qualification, we allow +| ourselves to reuse the ``.btn`` class on any element we choose, like + an ``a``, for +| example, or a ``button``. + +| Qualified selectors do not lend themselves well to being reused, and + every +| selector we write should be authored with reuse in mind. + +| Of course, there are times when you may want to legitimately qualify a +| selector—you might need to apply some very specific styling to a + particular +| element when it carries a certain class, for example: + +.. code:: css + + /** + * Embolden and color any element with a class of `.error`. + */ + .error { + color: red; + font-weight: bold; + } + + /** + * If the element is a `div`, also give it some box-like styling. + */ + div.error { + padding: 10px; + border: 1px solid; + } + +| This is one example where a qualified selector might be justifiable, + but I would +| still recommend an approach more like: + +.. code:: css + + /** + * Text-level errors. + */ + .error-text { + color: red; + font-weight: bold; + } + + /** + * Elements that contain errors. + */ + .error-box { + padding: 10px; + border: 1px solid; + } + +| This means that we can apply ``.error-box`` to any element, and not + just a +| ``div``—it is more reusable than a qualified selector. Quasi-Qualified Selectors -+++++++++++++++++++++++++ - -One thing that qualified selectors can be useful for is signaling where a class -might be expected or intended to be used, for example: +^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: css +| One thing that qualified selectors can be useful for is signaling + where a class +| might be expected or intended to be used, for example: - ul.nav { } +.. code:: css + ul.nav { } -Here we can see that the `.nav` class is meant to be used on a `ul` element, and -not on a `nav`. By using _quasi-qualified selectors_ we can still provide that -information without actually qualifying the selector: +| Here we can see that the ``.nav`` class is meant to be used on a + ``ul`` element, and +| not on a ``nav``. By using *quasi-qualified selectors* we can still + provide that +| information without actually qualifying the selector: -.. code-block:: css +.. code:: css - /*ul*/.nav { } + /*ul*/.nav { } - -By commenting out the leading element, we can still leave it to be read, but -avoid qualifying and increasing the specificity of the selector. +| By commenting out the leading element, we can still leave it to be + read, but +| avoid qualifying and increasing the specificity of the selector. Naming ------- +~~~~~~ As Phil Karlton once said -.. note:: - -'There are only two hard things in Computer Science: cache invalidation and naming things.' - -I won’t comment on the former claim here, but the latter has plagued me for -years. My advice with regard to naming things in CSS is to pick a name that is -sensible, but somewhat ambiguous: aim for high reusability. For example, instead -of a class like `.site-nav`, choose something like `.primary-nav`; rather than -`.footer-links`, favor a class like `.sub-links`. - -The differences in these names is that the first of each two examples is tied to -a very specific use case: they can only be used as the site’s navigation or the -footer’s links respectively. By using slightly more ambiguous names, we can -increase our ability to reuse these components in different circumstances. + ‘There are only two hard things in Computer Science: cache + invalidation and naming things.’ + +| I won’t comment on the former claim here, but the latter has plagued + me for +| years. My advice with regard to naming things in CSS is to pick a name + that is +| sensible, but somewhat ambiguous: aim for high reusability. For + example, instead +| of a class like ``.site-nav``, choose something like ``.primary-nav``; + rather than +| ``.footer-links``, favor a class like ``.sub-links``. + +| The differences in these names is that the first of each two examples + is tied to +| a very specific use case: they can only be used as the site’s + navigation or the +| footer’s links respectively. By using slightly more ambiguous names, + we can +| increase our ability to reuse these components in different + circumstances. To quote Nicolas Gallagher: -.. note:: - -Tying your class name semantics tightly to the nature of the content has already -reduced the ability of your architecture to scale or be easily put to use by -other developers. - -That is to say, we should use sensible names—classes like `.border` or `.red` -are never advisable—but we should avoid using classes which describe the exact -nature of the content and/or its use cases. **Using a class name to describe -content is redundant because content describes itself.** - -The debate surrounding semantics has raged for years, but it is important that -we adopt a more pragmatic, sensible approach to naming things in order to work -more efficiently and effectively. Instead of focussing on ‘semantics’, look more -closely at sensibility and longevity—choose names based on ease of maintenance, -not for their perceived meaning. - -Name things for people; they’re the only things that actually read your classes -(everything else merely matches them). Once again, it is better to strive for -reusable, recyclable classes rather than writing for specific use cases. Let’s -take an example: - -.. code-block:: css - - /** - * Runs the risk of becoming out of date; not very maintainable. - */ - .blue { color: blue; } - - /** - * Depends on location in order to be rendered properly. - */ - .header span { color: blue; } - - /** - * Too specific; limits our ability to reuse. - */ - .header-color { color: blue; } - - /** - * Nicely abstracted, very portable, doesn’t risk becoming out of date. - */ - .highlight-color { color: blue; } - - -It is important to strike a balance between names that do not literally describe -the style that the class brings, but also ones that do not explicitly describe -specific use cases. Instead of `.home-page-panel`, choose `.masthead`; instead -of `.site-nav`, favor `.primary-nav`; instead of `.btn-login`, opt for -`.btn-primary`. - + Tying your class name semantics tightly to the nature of the content + has already reduced the ability of your architecture to scale or be + easily put to use by other developers. + +| That is to say, we should use sensible names—classes like ``.border`` + or ``.red`` +| are never advisable—but we should avoid using classes which describe + the exact +| nature of the content and/or its use cases. **Using a class name to + describe + content is redundant because content describes itself.** + +| The debate surrounding semantics has raged for years, but it is + important that +| we adopt a more pragmatic, sensible approach to naming things in order + to work +| more efficiently and effectively. Instead of focussing on ‘semantics’, + look more +| closely at sensibility and longevity—choose names based on ease of + maintenance, +| not for their perceived meaning. + +| Name things for people; they’re the only things that actually read + your classes +| (everything else merely matches them). Once again, it is better to + strive for +| reusable, recyclable classes rather than writing for specific use + cases. Let’s +| take an example: + +.. code:: css + + /** + * Runs the risk of becoming out of date; not very maintainable. + */ + .blue { color: blue; } + + /** + * Depends on location in order to be rendered properly. + */ + .header span { color: blue; } + + /** + * Too specific; limits our ability to reuse. + */ + .header-color { color: blue; } + + /** + * Nicely abstracted, very portable, doesn’t risk becoming out of date. + */ + .highlight-color { color: blue; } + +| It is important to strike a balance between names that do not + literally describe +| the style that the class brings, but also ones that do not explicitly + describe +| specific use cases. Instead of ``.home-page-panel``, choose + ``.masthead``; instead +| of ``.site-nav``, favor ``.primary-nav``; instead of ``.btn-login``, + opt for +| ``.btn-primary``. Selector Performance --------------------- - -A topic which is—with the quality of today’s browsers—more interesting than it -is important, is selector performance. That is to say, how quickly a browser -can match the selectors your write in CSS up with the nodes it finds in the DOM. +~~~~~~~~~~~~~~~~~~~~ -Generally speaking, the longer a selector is (i.e. the more component parts) -the slower it is, for example: +| A topic which is—with the quality of today’s browsers—more interesting + than it +| is important, is selector performance. That is to say, how quickly a + browser +| can match the selectors your write in CSS up with the nodes it finds + in the DOM. -.. code-block:: css +| Generally speaking, the longer a selector is (i.e. the more component + parts) +| the slower it is, for example: - body.home div.header ul { } +.. code:: css + body.home div.header ul { } …is a far less efficient selector than: -.. code-block:: css - - .primary-nav { } - - -This is because browsers read CSS selectors right-to-left. A browser will read -the first selector as - -- find all `ul` elements in the DOM; -- now check if they live anywhere inside an element with a class of `.header`; -- next check that `.header` class exists on a `div` element; -- now check that that all lives anywhere inside any elements with a class of `.home`; -- finally, check that `.home` exists on a `body` element. - -The second, in contrast, is simply a case of the browser reading find all the -elements with a class of `.primary-nav`. - -To further compound the problem, we are using descendant selectors (e.g. -`.foo .bar {}`). The upshot of this is that a browser is required to start with -the rightmost part of the selector (i.e. `.bar`) and keep looking up the DOM -indefinitely until it finds the next part (i.e. `.foo`). This could mean -stepping up the DOM dozens of times until a match is found. - -This is just one reason why -**nesting with preprocessors is often a false economy**; as well as making -selectors unnecessarily more specific, and creating location dependency, it -also creates more work for the browser. - -By using a child selector (e.g. `.foo > .bar {}`) we can make the process much -more efficient, because this only requires the browser to look one level higher -in the DOM, and it will stop regardless of whether or not it found a match. +.. code:: css + + .primary-nav { } + +| This is because browsers read CSS selectors right-to-left. A browser + will read +| the first selector as + +- find all ``ul`` elements in the DOM; +- now check if they live anywhere inside an element with a class of + ``.header``; +- next check that ``.header`` class exists on a ``div`` element; +- now check that that all lives anywhere inside any elements with a + class of ``.home``; +- finally, check that ``.home`` exists on a ``body`` element. + +The second, in contrast, is simply a case of the browser reading find +all the elements with a class of ``.primary-nav``. + +| To further compound the problem, we are using descendant selectors + (e.g. +| ``.foo .bar {}``). The upshot of this is that a browser is required to + start with +| the rightmost part of the selector (i.e. ``.bar``) and keep looking up + the DOM +| indefinitely until it finds the next part (i.e. ``.foo``). This could + mean +| stepping up the DOM dozens of times until a match is found. + +| This is just one reason why +| **nesting with preprocessors is often a false economy**; as well as + making +| selectors unnecessarily more specific, and creating location + dependency, it +| also creates more work for the browser. + +| By using a child selector (e.g. ``.foo > .bar {}``) we can make the + process much +| more efficient, because this only requires the browser to look one + level higher +| in the DOM, and it will stop regardless of whether or not it found a + match. The Key Selector -++++++++++++++++ - -Because browsers read selectors right-to-left, the rightmost selector is often -critical in defining a selector’s performance: this is called the key selector. - -The following selector might appear to be highly performant at first glance. It -uses an ID which is nice and fast, and there can only ever be one on a page, so -surely this will be a nice and speedy lookup—just find that one ID and then -style everything inside of it: - -.. code-block:: css - - #foo * { } - - -The problem with this selector is that the key selector (`*`) is very, very far -reaching. What this selector actually does is find every single node in the DOM -(even `<title>`, `<link>`, and `<head>` elements; everything) and then looks to -see if it lives anywhere at any level within #foo. This is a very, very -expensive selector, and should most likely be avoided or rewritten. - -Thankfully, by writing selectors with good -**Selector Intent**, we are probably -avoiding inefficient selectors by default; we are very unlikely to have greedy -key selectors if we’re targeting the right things for the right reason. - -That said, however, CSS selector performance should be fairly low on your list -of things to optimize; browsers are fast, and are only ever getting faster, and -it is only on notable edge cases that inefficient selectors would be likely to -pose a problem. - -As well as their own specific issues, nesting, qualifying, and poor Selector -Intent all contribute to less efficient selectors. +^^^^^^^^^^^^^^^^ + +| Because browsers read selectors right-to-left, the rightmost selector + is often +| critical in defining a selector’s performance: this is called the key + selector. + +| The following selector might appear to be highly performant at first + glance. It +| uses an ID which is nice and fast, and there can only ever be one on a + page, so +| surely this will be a nice and speedy lookup—just find that one ID and + then +| style everything inside of it: + +.. code:: css + + #foo * { } + +| The problem with this selector is that the key selector (``*``) is + very, very far +| reaching. What this selector actually does is find every single node + in the DOM +| (even ``<title>``, ``<link>``, and ``<head>`` elements; everything) + and then looks to +| see if it lives anywhere at any level within #foo. This is a very, + very +| expensive selector, and should most likely be avoided or rewritten. + +| Thankfully, by writing selectors with good +| Selector Intent, we are probably +| avoiding inefficient selectors by default; we are very unlikely to + have greedy +| key selectors if we’re targeting the right things for the right + reason. + +| That said, however, CSS selector performance should be fairly low on + your list +| of things to optimize; browsers are fast, and are only ever getting + faster, and +| it is only on notable edge cases that inefficient selectors would be + likely to +| pose a problem. + +| As well as their own specific issues, nesting, qualifying, and poor + Selector +| Intent all contribute to less efficient selectors. General Rules -------------- - -Your selectors are fundamental to writing good CSS. To very briefly sum up the -above sections: - -- **Select what you want explicitly**, rather than relying on circumstance or coincidence. Good Selector Intent will rein in the reach and leak of your styles. -- **Write selectors for reusability**, so that you can work more efficiently and reduce waste and repetition. -- **Do not nest selectors unnecessarily**, because this will increase specificity and affect where else you can use your styles. -- **Do not qualify selectors unnecessarily**, as this will impact the number of different elements you can apply styles to. -- **Keep selectors as short as possible**, in order to keep specificity down and performance up. - -Focussing on these points will keep your selectors a lot more sane and easy to -work with on changing and long-running projects. - -**Further Reading** - -- `Shoot to kill; CSS selector intent <http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/`_ -- `‘Scope’ in CSS <http://csswizardry.com/2013/05/scope-in-css/`_ -- `Keep your CSS selectors short <http://csswizardry.com/2012/05/keep-your-css-selectors-short/`_ -- `About HTML semantics and front-end architecture <http://nicolasgallagher.com/about-html-semantics-front-end-architecture/`_ -- `Naming UI components in OOCSS <http://csswizardry.com/2014/03/naming-ui-components-in-oocss/`_ -- `Writing efficient CSS selectors <http://csswizardry.com/2011/09/writing-efficient-css-selectors/`_ +~~~~~~~~~~~~~ + +| Your selectors are fundamental to writing good CSS. To very briefly + sum up the +| above sections: + +- **Select what you want explicitly**, rather than relying on + circumstance or coincidence. Good Selector Intent will rein in the + reach and leak of your styles. +- **Write selectors for reusability**, so that you can work more + efficiently and reduce waste and repetition. +- **Do not nest selectors unnecessarily**, because this will increase + specificity and affect where else you can use your styles. +- **Do not qualify selectors unnecessarily**, as this will impact the + number of different elements you can apply styles to. +- **Keep selectors as short as possible**, in order to keep specificity + down and performance up. + +| Focussing on these points will keep your selectors a lot more sane and + easy to +| work with on changing and long-running projects. + +Further Reading +''''''''''''''' + +- `Shoot to kill; CSS selector intent`_ +- `‘Scope’ in CSS`_ +- `Keep your CSS selectors short`_ +- `About HTML semantics and front-end architecture`_ +- `Naming UI components in OOCSS`_ +- `Writing efficient CSS selectors`_ + + +.. _Shoot to kill; CSS selector intent: http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/ +.. _‘Scope’ in CSS: http://csswizardry.com/2013/05/scope-in-css/ +.. _Keep your CSS selectors short: http://csswizardry.com/2012/05/keep-your-css-selectors-short/ +.. _About HTML semantics and front-end architecture: http://nicolasgallagher.com/about-html-semantics-front-end-architecture/ +.. _Naming UI components in OOCSS: http://csswizardry.com/2014/03/naming-ui-components-in-oocss/ +.. _Writing efficient CSS selectors: http://csswizardry.com/2011/09/writing-efficient-css-selectors/ diff --git a/development/development/css_specificity.rst b/development/development/css_specificity.rst index e1ce8290..f776b045 100644 --- a/development/development/css_specificity.rst +++ b/development/development/css_specificity.rst @@ -1,408 +1,504 @@ Specificity -=========== +----------- -As we’ve seen, CSS isn’t the most friendly of languages: globally operating, -very leaky, dependent on location, hard to encapsulate, based on inheritance… -But! None of that even comes close to the horrors of specificity. +| As we’ve seen, CSS isn’t the most friendly of languages: globally + operating, +| very leaky, dependent on location, hard to encapsulate, based on + inheritance… +| But! None of that even comes close to the horrors of specificity. -No matter how well considered your naming, regardless of how perfect your -source order and cascade are managed, and how well you’ve scoped your rulesets, -just one overly-specific selector can undo everything. It is a gigantic -curveball, and undermines CSS’ very nature of the cascade, inheritance, and -source order. +| No matter how well considered your naming, regardless of how perfect + your +| source order and cascade are managed, and how well you’ve scoped your + rulesets, +| just one overly-specific selector can undo everything. It is a + gigantic +| curveball, and undermines CSS’ very nature of the cascade, + inheritance, and +| source order. -The problem with specificity is that it sets precedents and trumps that cannot -simply be undone. If we take the following example +| The problem with specificity is that it sets precedents and trumps + that cannot +| simply be undone. If we take the following example -.. code-block:: css +.. code:: css - #content table { } + #content table { } +| Not only does this exhibit poor +| **Selector Intent**, we didn’t actually +| want every ``table`` in the ``#content`` area. We wanted a specific + type of ``table`` +| that just happened to live there. This is a hugely over-specific + selector. It +| becomes apparent, when we needed a second type of ``table``: -Not only does this exhibit poor -**Selector Intent**, we didn’t actually want every `table` in the `#content` -area. We wanted a specific type of `table` that just happened to live there. -This is a hugely over-specific selector. It becomes apparent, when we needed a -second type of `table`: +.. code:: css -.. code-block:: css + #content table { } - #content table { } + /** + * Uh oh! My styles get overwritten by `#content table {}`. + */ + .my-new-table { } - /** - * Uh oh! My styles get overwritten by `#content table {}`. - */ - .my-new-table { } +| The first selector was trumping the specificity of the one defined + after it, +| working against CSS’ source-order based application of styles. In + order to +| remedy this, we have two main options. we could +#. refactor the CSS and HTML to remove that ID; +#. write a more specific selector to override it. -The first selector was trumping the specificity of the one defined after it, -working against CSS’ source-order based application of styles. In order to -remedy this, we have two main options. we could +| Unfortunately, refactoring would take a long time in a mature product + and the +| knock-on effects of removing this ID would be more substantial + business cost +| than the second option: just write a more specific selector. -1. refactor the CSS and HTML to remove that ID; -2. write a more specific selector to override it. +.. code:: css -Unfortunately, refactoring would take a long time in a mature product and the -knock-on effects of removing this ID would be more substantial business cost -than the second option: just write a more specific selector. + #content table { } -.. code-block:: css + #content .my-new-table { } - #content table { } - - #content .my-new-table { } - - -Now we have a selector that is even more specific still! And if we ever want to -override this one, we will need another selector of at least the same -specificity defined after it. We’ve started on a downward spiral. +| Now we have a selector that is even more specific still! And if we + ever want to +| override this one, we will need another selector of at least the same +| specificity defined after it. We’ve started on a downward spiral. Specificity can, among other things, -- limit your ability to extend and manipulate a codebase; -- interrupt and undo CSS’ cascading, inheriting nature; -- cause avoidable verbosity in your project; -- prevent things from working as expected when moved into different environments; -- lead to serious developer frustration. - -All of these issues are greatly magnified when working on a larger project with -a number of developers contributing code. +- limit your ability to extend and manipulate a codebase; +- interrupt and undo CSS’ cascading, inheriting nature; +- cause avoidable verbosity in your project; +- prevent things from working as expected when moved into different + environments; +- lead to serious developer frustration. +| All of these issues are greatly magnified when working on a larger + project with +| a number of developers contributing code. Keep It Low at All Times ------------------------- - -The problem with specificity isn’t necessarily that it’s high or low; it’s the -fact it is so variant and that it cannot be opted out of: the only way to deal -with it is to get progressively more specific—the notorious specificity wars we -looked at above. - -One of the single, simplest tips for an easier life when writing CSS, -particularly at any reasonable scale—is to always try to keep specificity as -low as possible at all times. Try to make sure there isn’t a lot of variance -between selectors in the codebase, and that all selectors strive for as low a -specificity as possible. - -Doing so will instantly help us tame and manage the project, meaning that no -overly-specific selectors are likely to impact or affect anything of a lower -specificity elsewhere. It also means we’re less likely to need to fight our way -out of specificity corners, and we’ll probably also be writing much smaller -stylesheets. +~~~~~~~~~~~~~~~~~~~~~~~~ + +| The problem with specificity isn’t necessarily that it’s high or low; + it’s the +| fact it is so variant and that it cannot be opted out of: the only way + to deal +| with it is to get progressively more specific—the notorious + specificity wars we +| looked at above. + +| One of the single, simplest tips for an easier life when writing CSS, +| particularly at any reasonable scale—is to always try to keep + specificity as +| low as possible at all times. Try to make sure there isn’t a lot of + variance +| between selectors in the codebase, and that all selectors strive for + as low a +| specificity as possible. + +| Doing so will instantly help us tame and manage the project, meaning + that no +| overly-specific selectors are likely to impact or affect anything of a + lower +| specificity elsewhere. It also means we’re less likely to need to + fight our way +| out of specificity corners, and we’ll probably also be writing much + smaller +| stylesheets. Simple changes to the way we work include, but are not limited to, -- not using IDs in your CSS; -- not nesting selectors; -- not qualifying classes; -- not chaining selectors. - -**Specificity can be wrangled and understood, but it is safer just to avoid it entirely.** +- not using IDs in your CSS; +- not nesting selectors; +- not qualifying classes; +- not chaining selectors. +**Specificity can be wrangled and understood, but it is safer just to +avoid it entirely.** IDs in CSS ----------- +~~~~~~~~~~ -If we want to keep specificity low, which we do, we have one really quick-win, -simple, easy-to-follow rule that we can employ to help us: +| If we want to keep specificity low, which we do, we have one really + quick-win, +| simple, easy-to-follow rule that we can employ to help us: .. warning:: **NEVER USE IDs in CSS** -Not only are IDs inherently non-reusable, they are also vastly more specific -than any other selector, and therefore become specificity anomalies. Where the -rest of your selectors are relatively low specificity, your ID-based selectors -are, comparatively, much, much higher. +| Not only are IDs inherently non-reusable, they are also vastly more + specific +| than any other selector, and therefore become specificity anomalies. + Where the +| rest of your selectors are relatively low specificity, your ID-based + selectors +| are, comparatively, much, much higher. -In fact, to highlight the severity of this difference, see how one thousand -chained classes cannot override the specificity of a single ID: -`jsfiddle.net/0yb7rque <http://jsfiddle.net/csswizardry/0yb7rque/`_. +| In fact, to highlight the severity of this difference, see how one + thousand +| chained classes cannot override the specificity of a single ID: +| `jsfiddle.net/0yb7rque`_. .. warning:: -(Please note that in Firefox you may see the text rendering in blue: this is a `known bug <https://twitter.com/codepo8/status/505004085398224896>`_, and an ID will be overridden by 256 chained classes.) +(Please note that in Firefox you may see the text rendering in blue: +this is a `known bug`_, and an ID will be overridden by 256 chained +classes.) .. note:: -**N.B.** It is still perfectly okay to use IDs in HTML and JavaScript; it is only in CSS that they prove troublesome. +**N.B.** It is still perfectly okay to use IDs in HTML and +JavaScript; it is only in CSS that they prove troublesome. -It is often suggested that developers who choose not to use IDs in CSS merely -don’t understand how specificity works. This is as incorrect as it is -offensive: no matter how experienced a developer you are, this behavior cannot -be circumvented; no amount of knowledge will make an ID less specific. +| It is often suggested that developers who choose not to use IDs in CSS + merely +| don’t understand how specificity works. This is as incorrect as it is +| offensive: no matter how experienced a developer you are, this + behavior cannot +| be circumvented; no amount of knowledge will make an ID less specific. -Opting into this way of working only introduces the chance of problems -occurring further down the line, and—particularly when working at scale—all -efforts should be made to avoid the potential for problems to arise. In a -sentence: +| Opting into this way of working only introduces the chance of problems +| occurring further down the line, and—particularly when working at + scale—all +| efforts should be made to avoid the potential for problems to arise. + In a +| sentence: **It is just not worth introducing the risk.** - Nesting -------- +~~~~~~~ -We’ve already looked at how nesting can lead to location dependent and -potentially inefficient code, but now it’s time to take a look at another of -its pitfalls: it makes selectors more specific. +| We’ve already looked at how nesting can lead to location dependent and +| potentially inefficient code, but now it’s time to take a look at + another of +| its pitfalls: it makes selectors more specific. -When we talk about nesting, we don’t necessarily mean preprocessor nesting, -like so: +| When we talk about nesting, we don’t necessarily mean preprocessor + nesting, +| like so: -.. code-block:: scss +.. code:: scss - .foo { + .foo { - .bar { } + .bar { } - } + } -We’re actually talking about descendant or child selectors; selectors which -rely on a thing within a thing. That could look like any one of the following: +| We’re actually talking about descendant or child selectors; selectors + which +| rely on a thing within a thing. That could look like any one of the + following: -.. code-block:: css +.. code:: css - /** - * An element with a class of `.bar` anywhere inside an element with a class of - * `.foo`. - */ - .foo .bar { } + /** + * An element with a class of `.bar` anywhere inside an element with a class of + * `.foo`. + */ + .foo .bar { } - /** - * An element with a class of `.module-title` directly inside an element with a - * class of `.module`. - */ - .module > .module-title { } + /** + * An element with a class of `.module-title` directly inside an element with a + * class of `.module`. + */ + .module > .module-title { } - /** - * Any `li` element anywhere inside a `ul` element anywhere inside a `nav` - * element - */ - nav ul li { } + /** + * Any `li` element anywhere inside a `ul` element anywhere inside a `nav` + * element + */ + nav ul li { } +| Whether you arrive at this CSS via a preprocessor or not isn’t + particularly +| important, but it is worth noting **that preprocessors tout this as a + feature, where it is actually to be avoided wherever possible.** -Whether you arrive at this CSS via a preprocessor or not isn’t particularly -important, but it is worth noting **that preprocessors tout this as a feature, -where it is actually to be avoided wherever possible.** +| Generally speaking, each part in a compound selector adds specificity. + Ergo, +| the fewer parts to a compound selector then the lower its overall + specificity, +| and we always want to keep specificity low. To quote Jonathan Snook: -Generally speaking, each part in a compound selector adds specificity. Ergo, -the fewer parts to a compound selector then the lower its overall specificity, -and we always want to keep specificity low. To quote Jonathan Snook: - -.. note:: - -…whenever declaring your styles, **use the least number of selectors required to style an element.** + …whenever declaring your styles, **use the least number of selectors + required to style an element.** Let’s look at an example: -.. code-block:: css - - .widget { - padding: 10px; - } - - .widget > .widget-title { - color: red; - } +.. code:: css + .widget { + padding: 10px; + } -To style an element with a class of `.widget-title`, we have a selector that -is twice as specific as it needs to be. That means that if we want to make any -modifications to `.widget-title`, we’ll need another at-least-equally specific -selector: + .widget > .widget-title { + color: red; + } -.. code-block:: css +| To style an element with a class of ``.widget-title``, we have a + selector that +| is twice as specific as it needs to be. That means that if we want to + make any +| modifications to ``.widget-title``, we’ll need another + at-least-equally specific +| selector: - .widget { ... } +.. code:: css - .widget > .widget-title { ... } + .widget { ... } - .widget > .widget-title-sub { - color: blue; - } + .widget > .widget-title { ... } + .widget > .widget-title-sub { + color: blue; + } -Not only is this entirely avoidable—we caused this problem ourselves—we have a -selector that is literally double the specificity it needs to be. We used 200% -of the specificity actually required. And not only that, but this also leads to -needless verbosity in our code—more to send over the wire. +| Not only is this entirely avoidable—we caused this problem + ourselves—we have a +| selector that is literally double the specificity it needs to be. We + used 200% +| of the specificity actually required. And not only that, but this also + leads to +| needless verbosity in our code—more to send over the wire. .. warning:: -As a rule, **if a selector will work without it being nested then do not nest it.** - +As a rule, **if a selector will work without it being nested then do +not nest it.** Scope ------ - -One possible advantage of nesting—which, unfortunately, does not outweigh the -disadvantages of increased specificity—is that it provides us with a namespace -of sorts. A selector like `.widget .title` scopes the styling of `.title` to an -element that only exists inside of an element carrying a class of `.widget`. - -This goes some way to providing our CSS with scope and encapsulation, but does -still mean that our selectors are twice as specific as they need to be. A -better way of providing this scope would be via a namespace—which does not lead -to an unnecessary increase in specificity. - -Now we have better scoped CSS with minimal specificity—the best of both worlds. - -**Further Reading** - -- `‘Scope’ in CSS <http://csswizardry.com/2013/05/scope-in-css/>`_ - - -`!important` ------------- - -The word `!important` sends shivers down the spines of almost all front-end -developers. `!important` is a direct manifestation of problems with -specificity; it is a way of cheating your way out of specificity wars, but -usually comes at a heavy price. It is often viewed as a last resort—a -desperate, defeated stab at patching over the symptoms of a much bigger problem -with your code. - -The general rule is that `!important` is always a bad thing, but, to quote -Jamie Mason: - -.. note:: - -Rules are the children of principles. - -That is to say, a single rule is a simple, black-and-white way of adhering to a -much larger principle. When you’re starting out, the rule never use -`!important` is a good one. - -However, once you begin to grow and mature as a developer, you begin to -understand that the principle behind that rule is simply about keeping -specificity low. You’ll also learn when and where the rules can be bent… - -`!important` does have a place in CSS projects, but only if used sparingly and -proactively. - -Proactive use of `!important` is when it is used _before_ you’ve encountered -any specificity problems; when it is used as a guarantee rather than as a fix. +~~~~~ + +| One possible advantage of nesting—which, unfortunately, does not + outweigh the +| disadvantages of increased specificity—is that it provides us with a + namespace +| of sorts. A selector like ``.widget .title`` scopes the styling of + ``.title`` to an +| element that only exists inside of an element carrying a class of + ``.widget``. + +| This goes some way to providing our CSS with scope and encapsulation, + but does +| still mean that our selectors are twice as specific as they need to + be. A +| better way of providing this scope would be via a namespace—which does + not lead +| to an unnecessary increase in specificity. + +Now we have better scoped CSS with minimal specificity—the best of both +worlds. + +Further Reading +''''''''''''''' + +- `‘Scope’ in CSS`_ + +``!important`` +~~~~~~~~~~~~~~ + +| The word ``!important`` sends shivers down the spines of almost all + front-end +| developers. ``!important`` is a direct manifestation of problems with +| specificity; it is a way of cheating your way out of specificity wars, + but +| usually comes at a heavy price. It is often viewed as a last resort—a +| desperate, defeated stab at patching over the symptoms of a much + bigger problem +| with your code. + +| The general rule is that ``!important`` is always a bad thing, but, to + quote +| Jamie Mason: + + Rules are the children of principles. + +| That is to say, a single rule is a simple, black-and-white way of + adhering to a +| much larger principle. When you’re starting out, the rule never use +| ``!important`` is a good one. + +| However, once you begin to grow and mature as a developer, you begin + to +| understand that the principle behind that rule is simply about keeping +| specificity low. You’ll also learn when and where the rules can be + bent… + +| ``!important`` does have a place in CSS projects, but only if used + sparingly and +| proactively. + +| Proactive use of ``!important`` is when it is used *before* you’ve + encountered +| any specificity problems; when it is used as a guarantee rather than + as a fix. For example: -.. code-block:: css - - .one-half { - width: 50% !important; - } - - .hidden { - display: none !important; - } - - -These two helper, or _utility_, classes are very specific in their intentions: -you would only use them if you wanted something to be rendered at 50% width or -not rendered at all. If you didn’t want this behavior, you would not use these -classes, therefore whenever you do use them you will definitely want them to -win. - -Here we proactively apply `!important` to ensure that these styles always win. -This is the correct use of `!important` to guarantee that these trumps always -work, and don’t accidentally get overridden by something else more specific. - -Incorrect, reactive use of `!important` is when it is used to combat -specificity problems after the fact: applying `!important` to declarations -because of poorly architected CSS. For example, let’s imagine we have this HTML: - -.. code-block:: html - - <div class="content"> - <h2 class="heading-sub">...</h2> - </div> +.. code:: css + + .one-half { + width: 50% !important; + } + + .hidden { + display: none !important; + } + +| These two helper, or *utility*, classes are very specific in their + intentions: +| you would only use them if you wanted something to be rendered at 50% + width or +| not rendered at all. If you didn’t want this behavior, you would not + use these +| classes, therefore whenever you do use them you will definitely want + them to +| win. + +| Here we proactively apply ``!important`` to ensure that these styles + always win. +| This is the correct use of ``!important`` to guarantee that these + trumps always +| work, and don’t accidentally get overridden by something else more + specific. + +| Incorrect, reactive use of ``!important`` is when it is used to combat +| specificity problems after the fact: applying ``!important`` to + declarations +| because of poorly architected CSS. For example, let’s imagine we have + this HTML: + +.. code:: html + + <div class="content"> + <h2 class="heading-sub">...</h2> + </div> …and this CSS: -.. code-block:: css +.. code:: css - .content h2 { - font-size: 2rem; - } + .content h2 { + font-size: 2rem; + } - .heading-sub { - font-size: 1.5rem !important; - } + .heading-sub { + font-size: 1.5rem !important; + } -Here we can see how we’ve used `!important` to force our `.heading-sub {}` -styles to reactively override our `.content h2 {}` selector. This could have -been circumvented by any number of things, including using better Selector -Intent, or avoiding nesting. +| Here we can see how we’ve used ``!important`` to force our + ``.heading-sub {}`` +| styles to reactively override our ``.content h2 {}`` selector. This + could have +| been circumvented by any number of things, including using better + Selector +| Intent, or avoiding nesting. -In these situations, it is preferable that you investigate and refactor any -offending rulesets to try and bring specificity down across the board, as -opposed to introducing such specificity heavyweights. +| In these situations, it is preferable that you investigate and + refactor any +| offending rulesets to try and bring specificity down across the board, + as +| opposed to introducing such specificity heavyweights. .. warning:: -**Only use** `!important` **proactively, not reactively.** - +**Only use** ``!important`` **proactively, not reactively.** Hacking Specificity -------------------- - -With all that said on the topic of specificity, and keeping it low, it is -inevitable that we will encounter problems. No matter how hard we try, and how -conscientious we are, there will always be times that we need to hack and -wrangle specificity. - -When these situations do arise, it is important that we handle the hacks as -safely and elegantly as possible. - -In the event that you need to increase the specificity of a class selector, -there are a number of options. We could nest the class inside something else to -bring its specificity up. For example, we could use `.header .site-nav {}` to -bring up the specificity of a simple `.site-nav {}` selector. - -The problem with this, as we’ve discussed, is that it introduces location -dependency: these styles will only work when the `.site-nav` component is in -the `.header` component. - -Instead, we can use a much safer hack that will not impact this component’s -portability: we can chain that class with itself: - -.. code-block:: css - - .site-nav.site-nav { } - -This chaining doubles the specificity of the selector, but does not introduce -any dependency on location. - -In the event that we do, for whatever reason, have an ID in our markup that we -cannot replace with a class, select it via an attribute selector as opposed to -an ID selector. For example, let’s imagine we have embedded a third-party -widget on our page. We can style the widget via the markup that it outputs, but -we have no ability to edit that markup ourselves: - -.. code-block:: html - - <div id="third-party-widget"> - ... - </div> - -Even though we know not to use IDs in CSS, what other option do we have? We -want to style this HTML but have no access to it, and all it has on it is an ID. +~~~~~~~~~~~~~~~~~~~ + +| With all that said on the topic of specificity, and keeping it low, it + is +| inevitable that we will encounter problems. No matter how hard we try, + and how +| conscientious we are, there will always be times that we need to hack + and +| wrangle specificity. + +| When these situations do arise, it is important that we handle the + hacks as +| safely and elegantly as possible. + +| In the event that you need to increase the specificity of a class + selector, +| there are a number of options. We could nest the class inside + something else to +| bring its specificity up. For example, we could use + ``.header .site-nav {}`` to +| bring up the specificity of a simple ``.site-nav {}`` selector. + +| The problem with this, as we’ve discussed, is that it introduces + location +| dependency: these styles will only work when the ``.site-nav`` + component is in +| the ``.header`` component. + +| Instead, we can use a much safer hack that will not impact this + component’s +| portability: we can chain that class with itself: + +.. code:: css + + .site-nav.site-nav { } + +| This chaining doubles the specificity of the selector, but does not + introduce +| any dependency on location. + +| In the event that we do, for whatever reason, have an ID in our markup + that we +| cannot replace with a class, select it via an attribute selector as + opposed to +| an ID selector. For example, let’s imagine we have embedded a + third-party +| widget on our page. We can style the widget via the markup that it + outputs, but +| we have no ability to edit that markup ourselves: + +.. code:: html + + <div id="third-party-widget"> + ... + </div> + +| Even though we know not to use IDs in CSS, what other option do we + have? We +| want to style this HTML but have no access to it, and all it has on it + is an ID. We do this: -.. code-block:: css +.. code:: css + + [id="third-party-widget"] { } - [id="third-party-widget"] { } +| Here we are selecting based on an attribute rather than an ID, and + attribute +| selectors have the same specificity as a class. This allows us to + style based +| on an ID, but without introducing its specificity. -Here we are selecting based on an attribute rather than an ID, and attribute -selectors have the same specificity as a class. This allows us to style based -on an ID, but without introducing its specificity. +| Do keep in mind that these are hacks, and should not be used unless + you have no +| better alternative. -Do keep in mind that these are hacks, and should not be used unless you have no -better alternative. +Further Reading +''''''''''''''' -**Further Reading** +- `Hacks for dealing with specificity`_ -- `Hacks for dealing with specificity <http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/'_ +.. _jsfiddle.net/0yb7rque: http://jsfiddle.net/csswizardry/0yb7rque/ +.. _known bug: https://twitter.com/codepo8/status/505004085398224896 +.. _‘Scope’ in CSS: http://csswizardry.com/2013/05/scope-in-css/ +.. _Hacks for dealing with specificity: http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/ diff --git a/development/development/css_standards.rst b/development/development/css_standards.rst new file mode 100644 index 00000000..a21348c0 --- /dev/null +++ b/development/development/css_standards.rst @@ -0,0 +1,362 @@ +| In working on large, long running projects with dozens of developers, + it is +| important that we all work in a unified way in order to, among other + things: + +- Keep code maintainable +- Keep code transparent and readable +- Keep code scalable + +| There are a variety of techniques we must employ in order to satisfy + these +| goals. + +The Importance of a Styleguide +------------------------------ + +| A coding styleguide (note, not a visual styleguide) is a valuable tool + for teams +| who + +- build and maintain products for a reasonable length of time; +- have developers of differing abilities and specialisms; +- have a number of different developers working on a product at any + given time; +- on-board new staff regularly; +- have a number of codebases that developers dip in and out of. + +| Whilst styleguides are typically more suited to production teams—large + codebases +| on long-lived and evolving projects, with multiple developers + contributing over +| prolonged periods of time—all developers should strive for a degree of +| standardization in their code. + +A good styleguide, when well followed, will + +- set the standard for code quality across a codebase; +- promote consistency across codebases; +- give developers a feeling of familiarity across codebases; +- increase productivity. + +Disclaimers +~~~~~~~~~~~ + +| These Guidelines are a styleguide; they may not be the styleguide. + They contain +| methodologies, techniques, and tips that we firmly recommend to teams + +| They are opinionated, but have been repeatedly tried, tested, + stressed, refined, +| broken, reworked, and revisited over a number of years on projects of + all sizes. + +| They should be learned, understood, and implemented at all times on + this +| project, any deviation must be fully justified. + +Some General principles +----------------------- + + “Part of being a good steward to a successful project is realizing + that writing code for yourself is a Bad Idea™. If thousands of + people are using your code, then write your code for maximum + clarity, not your personal preference of how to get clever within + the spec.” - Idan Gazit + +- Don’t try to prematurely optimize your code; keep it readable and + understandable. +- All code should look like a single person typed it, even when many + people are contributing to it. +- We use a strictly enforced agreed-upon style based on existing common + patterns. + +Meaningful Whitespace +--------------------- + +| Only one style should exist across the entire source of all your + code-base. +| Always be consistent in your use of whitespace. Use whitespace to + improve +| readability. + +- Never mix spaces and tabs for indentation. Stick to your choice + without fail. (**Preference: tabs**) +- Choose the number of preferred characters used per indentation level. + (**Preference: 4 spaces**) + +.. warning:: + +configure your editor to “show invisibles” or to automatically remove +end-of-line whitespace. The use of an `EditorConfig`_ file is being used +to help maintain the basic whitespace conventions. + +| As well as indentation, we can provide a lot of information through + liberal and +| judicious use of whitespace between rulesets. We use: + +- One (1) empty line between closely related rulesets. +- Two (2) empty lines between loosely related rulesets. + +For example: + +.. code:: scss + + //------------------------------------------------------------------------------ + // #FOO + //------------------------------------------------------------------------------ + + .foo { } + + .foo__bar { } + + + .foo--baz { } + +| There should never be a scenario in which two rulesets do not have an + empty line +| between them. This would be incorrect: + +.. code:: scss + + .foo { } + .foo__bar { } + .foo--baz { } + +Multiple Files +~~~~~~~~~~~~~~ + +| With the meteoric rise of preprocessors of late, more often is the + case that +| developers are splitting CSS across multiple files. + +| Even if not using a preprocessor, it is a good idea to split discrete + chunks of +| code into their own files, which are concatenated during a build step. + +| We follow the ITCSS principles for the organization of our code and as + such +| everything is broken up into partials. All partials are to be named to + reflect +| the contained component/module and lead by an underscore(\ ``_``) to + prevent self +| rendering. + +Commenting +---------- + +**CSS needs more comments.** + +| The cognitive overhead of working with CSS is huge. With so much to be + aware of, +| and so many project-specific nuances to remember, the worst situation + most +| developers find themselves in is being + the-person-who-didn’t-write-this-code. +| Remembering your own classes, rules, objects, and helpers is + manageable to an +| extent, but anyone inheriting CSS barely stands a chance. + +| This is why well commented code is extremely important. Take time to + describe +| components, how they work, their limitations, and the way they are + constructed. +| Don’t leave others in the project guessing as to the purpose of + uncommon or +| non-obvious code. + +Comment style should be simple and consistent within the code base. + +- Place comments on a new line above their subject. +- Keep line-length to a sensible maximum, e.g., 80 columns. +- Make liberal use of comments to break CSS code into discrete + sections. +- Use “sentence case” comments and consistent text indentation. + +| As CSS is something of a declarative language that doesn’t really + leave much of +| a paper-trail, it is often hard to discern—from looking at the CSS + alone— + +- whether some CSS relies on other code elsewhere; +- what effect changing some code will have elsewhere; +- where else some CSS might be used; +- what styles something might inherit (intentionally or otherwise); +- what styles something might pass on (intentionally or otherwise); +- where the author intended a piece of CSS to be used. + +| This doesn’t even take into account some of CSS’ many quirks—such as + various +| sates of ``overflow`` triggering block formatting context, or certain + transform +| properties triggering hardware acceleration—that make it even more + baffling to +| developers inheriting projects. + +As a result of CSS not telling its own story very well, it is a + language that +| really does benefit from being heavily commented. + +| As a rule, you should comment anything that isn’t immediately obvious + from the +| code alone. That is to say, there is no need to tell someone that + ``color: red;`` +| will make something red, but if you’re using ``overflow: hidden;`` to + clear +| floats—as opposed to clipping an element’s overflow—this is probably + something +| worth documenting. + +.. warning:: + +Tip: you can configure your editor to provide you with shortcuts to +output agreed-upon comment patterns. + +Comment Example: + +.. code:: scss + + //------------------------------------------------------------------------------ + // #[LAYER]: PARTIAL NAME + //------------------------------------------------------------------------------ + // #description + // + // This is a description of the PARTIAL + // + //------------------------------------------------------------------------------ + + // + // #settings + + // Layout Variables + $variable: [value] + + // Theme Variables + $variable: [value] + + // + // #scss + + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } + + // + // Section Block Comment + //------------------------------------------------------------------------------ + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } + +Low-level +~~~~~~~~~ + +| Oftentimes we want to comment on specific declarations (i.e. lines) in + a +| ruleset. To do this we use a kind of reverse footnote. Here is a more + complex +| comment detailing the larger site headers mentioned above: + +.. code:: scss + + // + // 1. Allow us to style box model properties. + // 2. Line different sized buttons up a little nicer. + // 3. Make buttons inherit font styles (often necessary when styling `input`s as + // buttons). + // 4. Reset/normalize some styles. + // 5. Force all button-styled elements to appear clickable. + // 6. Fixes odd inner spacing in IE7. + // 7. Subtract the border size from the padding value so that buttons do not + // grow larger as we add borders. + // 8. Prevent button text from being selectable. + // 9. Prevent default browser outline halo + // + .o-btn { + @include type(button); + @include shadow(2); + line-height: unitless($btn-height, map-get(map-get($type-styles, button), font-size)); + text-align: center; // [4] + vertical-align: middle; // [2] + white-space: nowrap; + text-decoration: none; // [4] + background-color: $btn-background-color; + border: none; + border-radius: $btn-border-radius; + outline: none; // [9] + color: $btn-text-color; + position: relative; + display: inline-block; // [1] + overflow: hidden; // [6] + min-width: $btn-min-width; + margin: 0; // [4] + padding: 0 $btn-spacing; // [7] + cursor: pointer; + user-select: none; // [8] + transition: + box-shadow 0.2s $animation-curve-fast-out-linear-in, + background-color 0.2s $default-animation-curve, + color 0.2s $default-animation-curve; + will-change: box-shadow; + } + +| These types of comment allow us to keep all of our documentation in + one place +| whilst referring to the parts of the ruleset to which they belong. + +Titling +~~~~~~~ + +Begin every new major section of a CSS project with a title: + +.. code:: scss + + //------------------------------------------------------------------------------ + // #SECTION-TITLE + //------------------------------------------------------------------------------ + + .selector { } + +| The title of the section is prefixed with a hash (``#``) symbol to + allow us to +| perform more targeted searches (e.g. ``grep``, etc.): instead of + searching for +| just ``SECTION-TITLE``—which may yield many results—a more scoped + search of +| ``#SECTION-TITLE`` should return only the section in question. + +| Leave a carriage return between this title and the next line of code + (be that a +| comment, some Sass, or some CSS). + +Preprocessor Comments +~~~~~~~~~~~~~~~~~~~~~ + +| With most—if not all—preprocessors, we have the option to write + comments that +| will not get compiled out into our resulting CSS file. As a rule, use + these +| comments to speed up and prevent errors in the minification step. + +.. _EditorConfig: http://editorconfig.org/ From 90413cf12cd1830a1ddc0a8174eebe3e22061f9d Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 5 Oct 2017 02:41:32 -0400 Subject: [PATCH 15/98] attempt to fix spacing of guidelines --- development/development/css_guidelines.rst | 189 +++++---------------- 1 file changed, 40 insertions(+), 149 deletions(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index c8e12fbf..e5000908 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -1,46 +1,20 @@ Introduction ------------ -| CSS is not a pretty language. While it is simple to learn and get - started with, -| it soon becomes problematic at any reasonable scale. There isn’t much - we can do -| to change how CSS works, but we can make changes to the way we author - and -| structure it. - -| There are a variety of techniques we must employ in order to satisfy - these -| goals, and CSS Guidelines is a document of recommendations and - approaches that -| will help us to do so. - -| The first part of this will deal with syntax, formatting and CSS - anatomy, the -| second part will deal with approach, mindframe and attitude toward - writing and -| architecting CSS. +CSS is not a pretty language. While it is simple to learn and get started with, it soon becomes problematic at any reasonable scale. There isn’t much we can do to change how CSS works, but we can make changes to the way we author and structure it. + +There are a variety of techniques we must employ in order to satisfy these goals, and CSS Guidelines is a document of recommendations and approaches that will help us to do so. + +The first part of this will deal with syntax, formatting and CSS anatomy, the second part will deal with approach, mindframe and attitude toward writing and architecting CSS. Syntax and Formatting --------------------- -| One of the simplest forms of a styleguide is a set of rules regarding - syntax and -| formatting. Having a standard way of writing (literally writing) CSS - means that -| code will always look and feel familiar to all members of the team. +One of the simplest forms of a styleguide is a set of rules regarding syntax and formatting. Having a standard way of writing (literally writing) CSS means that code will always look and feel familiar to all members of the team. -| Further, code that looks clean feels clean. It is a much nicer - environment to -| work in, and prompts other team members to maintain the standard of - cleanliness -| that they found. Ugly code sets a bad precedent. +Further, code that looks clean feels clean. It is a much nicer environment to work in, and prompts other team members to maintain the standard of cleanliness that they found. Ugly code sets a bad precedent. -| The chosen code format must ensure that code is: easy to read; easy to - clearly -| comment; minimizes the chance of accidentally introducing errors; and - results in -| useful diffs and blames. +The chosen code format must ensure that code is: easy to read; easy to clearly comment; minimizes the chance of accidentally introducing errors; and results in useful diffs and blames. At a very high-level, we want @@ -52,9 +26,7 @@ At a very high-level, we want Anatomy of a Ruleset ~~~~~~~~~~~~~~~~~~~~ -| Before we discuss how we write out our rulesets, let’s first - familiarize -| ourselves with the relevant terminology: +Before we discuss how we write out our rulesets, let’s first familiarize ourselves with the relevant terminology: The following is a ``[ruleset]`` @@ -72,26 +44,20 @@ Formating ~~~~~~~~~ - Use one discrete selector per line in multi-selector rulesets. -- The opening brace (``{``) should be on the same line as our last - selector. +- The opening brace (``{``) should be on the same line as our last selector. - Include a single space before the opening brace (``{``). - Include properties and values on the same line. - Include one declaration per line in a declaration block. - Use one level of indentation for each declaration. - Include a single space after the colon (``:``) of a declaration. - Use lowercase hex values, e.g., #abc123. -- Use quotes consistently. **Preference double quotes**, e.g., - ``content: ""``. -- Always quote attribute values in selectors, e.g., - ``input[type="checkbox"]``. +- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""``. +- Always quote attribute values in selectors, e.g., ``input[type="checkbox"]``. - Avoid specifying units for zero-values, e.g., ``margin: 0``. - Always use leading zeros, e.g, ``font-size: 0.875rem`` -- Include a space after each comma(\ ``,``) in comma-separated property - or function values. -- Include a semi-colon(\ ``;``) at the end of every declaration - including the last in a declaration block. -- Place the closing brace (``}``) of a ruleset in the same column as - the first character of the ruleset, on its own line. +- Include a space after each comma(\ ``,``) in comma-separated property or function values. +- Include a semi-colon(\ ``;``) at the end of every declaration including the last in a declaration block. +- Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line. - Separate each ruleset by a blank line. Example: @@ -117,9 +83,7 @@ Example: padding: 10px; } -| This format seems to be the largely universal standard (except for - variations in -| indentation). +This format seems to be the largely universal standard (except for variations in indentation). As such, the following would be incorrect: @@ -143,17 +107,12 @@ Problems here include Multi-line CSS ~~~~~~~~~~~~~~ -| CSS should be written across multiple lines, except in very specific -| circumstances. There are a number of benefits to this: +CSS should be written across multiple lines, except in very specific circumstances. There are a number of benefits to this: -- A reduced chance of merge conflicts, because each piece of - functionality exists on its own line. -- More ‘truthful’ and reliable ``diffs``, because one line only ever - carries one change. +- A reduced chance of merge conflicts, because each piece of functionality exists on its own line. +- More ‘truthful’ and reliable ``diffs``, because one line only ever carries one change. -| Exceptions to this rule should be fairly apparent, such as similar - rulesets -| that only carry one declaration each, for example: +Exceptions to this rule should be fairly apparent, such as similar rulesets that only carry one declaration each, for example: .. code:: css @@ -172,17 +131,12 @@ Multi-line CSS These types of ruleset benefit from being single-lined because - they still conform to the one-reason-to-change-per-line rule; -- they share enough similarities that they don’t need to be read as - thoroughly as other rulesets—there is more benefit in being able to - scan their selectors, which are of more interest to us in these - cases. +- they share enough similarities that they don’t need to be read as thoroughly as other rulesets—there is more benefit in being able to scan their selectors, which are of more interest to us in these cases. Declaration order ~~~~~~~~~~~~~~~~~ -| declarations are to be consistently ordered by related property - declarations -| following the order +declarations are to be consistently ordered by related property declarations following the order #. Typographic #. Visual @@ -229,94 +183,43 @@ Example: Proper Use of units ~~~~~~~~~~~~~~~~~~~ -| CSS allows for the use of several different unit types. As such it can - get -| confusing when using more than one type of unit through out the - project. For -| that reason its beneficial to stick to a stick set of rules for what - unit types -| are to be used for certain selectors. +CSS allows for the use of several different unit types. As such it can get confusing when using more than one type of unit through out the project. For that reason its beneficial to stick to a stick set of rules for what unit types are to be used for certain selectors. -| Furthermore there are certain reasons to use or avoid using specific - units in -| certain places. +Furthermore there are certain reasons to use or avoid using specific units in certain places. EM ^^ -| The ‘em’ unit. This is a very problematic unit which reeks havoc on - countless -| projects due to the way its calculated. As such this unit type must be - avoid -| except for very very minimal use cases. We prevent the use of ``em`` - except for -| ``letter-spaceing`` & ``word-spacing``. It is also used for icon - sizing but that is -| an edge case. +The ‘em’ unit. This is a very problematic unit which reeks havoc on countless projects due to the way its calculated. As such this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for ``letter-spaceing`` & ``word-spacing``. It is also used for icon sizing but that is an edge case. Line-heights ^^^^^^^^^^^^ -| All line-heights are to be specified as ``unitless`` in order to - prevent in proper -| inheritance. By nature when using units with line-heights the children - inherit -| by default. This can lead to unwanted effects and bloated code. A - ``sass`` -| function called ``unitless`` is provided which will convert px values - for -| convenience, but for clarity the math is simply +All line-heights are to be specified as ``unitless`` in order to prevent in proper inheritance. By nature when using units with line-heights the children inherit by default. This can lead to unwanted effects and bloated code. A ``sass`` function called ``unitless`` is provided which will convert px values for convenience, but for clarity the math is simply .. code:: scss - line-height: (desired px value) / (current elements font-size) + line-height: (desired px value) / (current elements font-size) Font-size ^^^^^^^^^ -| All ``font-size`` should be specified either in ``px`` or ``%`` in - small cases. All px -| values will be converted to ``rem`` during the build process as - ``rem`` provide for -| control in responsive situations. +All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. All px values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. Margins & Paddings ^^^^^^^^^^^^^^^^^^ -| All ``margin`` & ``padding`` should be specified in ``px`` values or - ``%``. All ``px`` All -| px values will be converted to ``rem`` during the build process as - ``rem`` provide -| for control in responsive situations. +All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` All px values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. PX ^^ -| All ``px`` will be whole numbers. Browsers do not render ``px`` in - fractional values -| despite what you browser may say it is. Only calculated values will - display as -| fractional ``px``. For clarification a calculated value would be units - like ``rem``, -| ``em``, ``%``, & even ``unitless`` as is the case with line-heights. +All ``px`` will be whole numbers. Browsers do not render ``px`` in fractional values despite what you browser may say it is. Only calculated values will display as fractional ``px``. For clarification a calculated value would be units like ``rem``, ``em``, ``%``, & even ``unitless`` as is the case with line-heights. Dimensions ^^^^^^^^^^ -| All dimensional values ``width``, ``min-width``, ``height``, & - ``min-height`` should be -| specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, - but they are still -| on the fringe of browser acceptance, as such fallbacks in ``px`` or - ``%`` are -| required. These values will remain as px if specified. This is done as - ``height`` -| is more effectively and appropriately controlled via the - ``line-height`` property, -| and ``width`` is better specified using the objects box-model via - ``padding`` unless -| its fluid in which ``100%`` can be specified or u can also use -| ``left: 0; right: 0;`` +All dimensional values ``width``, ``min-width``, ``height``, & ``min-height`` should be specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, but they are still on the fringe of browser acceptance, as such fallbacks in ``px`` or ``%`` are required. These values will remain as px if specified. This is done as ``height`` is more effectively and appropriately controlled via the ``line-height`` property, and ``width`` is better specified using the objects box-model via ``padding`` unless its fluid in which ``100%`` can be specified or u can also use ``left: 0; right: 0;`` Indenting Sass ^^^^^^^^^^^^^^ @@ -340,58 +243,46 @@ Sass provides nesting functionality. That is to say, by writing this: .foo { color: red; } .foo .bar { color: blue; } -| When indenting Sass, we stick to the same two indentation, and we also - leave a -| blank line before and after the nested ruleset. +When indenting Sass, we stick to the same two indentation, and we also leave a blank line before and after the nested ruleset. -**N.B.** Nesting in Sass should be avoided in most cases. See the -Specificity section for more data +**N.B.** Nesting in Sass should be avoided in most cases. See the Specificity section for more data -Enforcing standardisation +Enforcing standardization ~~~~~~~~~~~~~~~~~~~~~~~~~ -Our project makes use of several tools to lint and to keep us to the -standards. +Our project makes use of several tools to lint and to keep us to the standards. 1. `stylelint.io`_ ^^^^^^^^^^^^^^^^^^ .. note:: -This is used to provide detailed linting for our standards via the -``.stlyelintrc`` file in the root of the project. +This is used to provide detailed linting for our standards via the ``.stlyelintrc`` file in the root of the project. 2. `postcss-sorting`_ ^^^^^^^^^^^^^^^^^^^^^ .. note:: -This is used to provide automatic sorting to our declaration order -via the ``.postcss-sorting.json`` file in the root of the project. +This is used to provide automatic sorting to our declaration order via the ``.postcss-sorting.json`` file in the root of the project. 3. `postcss-pxtorem`_ ^^^^^^^^^^^^^^^^^^^^^ .. note:: -This is used to ensure the proper units are consistently used -throughout the project during the build process via the ``gulp`` as well -as on save in your editor. +This is used to ensure the proper units are consistently used throughout the project during the build process via the ``gulp`` as well as on save in your editor. 4. `stylefmt`_ ^^^^^^^^^^^^^^ .. note:: -This is used to help automatically re-format your code to the -standards on the fly during the build process via ``gulp`` as well as on -save in your editor. +This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. .. note:: -As a **NOTE** our editor of choice is `ATOM`_ which provides usefull -plugins to make use of these tools. Checkout the `Editor Setup`_ section -of the docs for more information +As a **NOTE** our editor of choice is `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information .. _stylelint.io: http://www.stylelint.io .. _postcss-sorting: https://github.com/hudochenkov/postcss-sorting From 86fb1f73fe7609165d86ba35c77074dbe9b7880f Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 5 Oct 2017 02:56:00 -0400 Subject: [PATCH 16/98] fix naming spacing --- development/development/css_naming.rst | 191 +++++-------------------- 1 file changed, 38 insertions(+), 153 deletions(-) diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst index 09871a7a..b69471c7 100644 --- a/development/development/css_naming.rst +++ b/development/development/css_naming.rst @@ -1,9 +1,7 @@ Naming Conventions ------------------ -| Naming conventions in CSS are hugely useful in making your code more - strict, -| more transparent, and more informative. +Naming conventions in CSS are hugely useful in making your code more strict, more transparent, and more informative. A good naming convention will tell you and your team @@ -17,11 +15,7 @@ The naming convention we follow are as follows - Layer namespacing - A variation on BEM-like naming for action modifiers -| It’s worth noting that not all the naming convention are normally - useful -| in the CSS-side of development; they really come into their own when - viewed in -| HTML. +It’s worth noting that not all the naming convention are normally useful in the CSS-side of development; they really come into their own when viewed in HTML. Hyphen Delimited ~~~~~~~~~~~~~~~~ @@ -34,9 +28,7 @@ All strings in classes are delimited with a hyphen (``-``), like so: .sub-content { } -| Camel case and underscores are not used for regular classes; the - following are -| incorrect: +Camel case and underscores are not used for regular classes; the following are incorrect: .. code:: css @@ -47,19 +39,9 @@ All strings in classes are delimited with a hyphen (``-``), like so: Modified BEM-like Naming ~~~~~~~~~~~~~~~~~~~~~~~~ -| For larger, more interrelated pieces of UI that require a number of - classes, we -| use a modified BEM-like naming convention. +For larger, more interrelated pieces of UI that require a number of classes, we use a modified BEM-like naming convention. -| BEM, meaning Block, Element, Modifier, is a front-end methodology - coined by -| developers working at Yandex. Whilst BEM is a complete methodology, - here we are -| only concerned with its naming convention. Further, the naming - convention here -| only is BEM-like; the principles are exactly the same, but the actual - syntax -| differs. +BEM, meaning Block, Element, Modifier, is a front-end methodology coined by developers working at Yandex. Whilst BEM is a complete methodology, here we are only concerned with its naming convention. Further, the naming convention here only is BEM-like; the principles are exactly the same, but the actual syntax differs. BEM splits components’ classes into three groups: @@ -75,28 +57,14 @@ To take an analogy (note, not an example): .dropdown-item { } .dropdown--active { } -| Elements are delimited with two (hyphens (``-``), and Modifiers are - delimited by -| two (2) hyphens (``--``). +Elements are delimited with two (hyphens (``-``), and Modifiers are delimited by two (2) hyphens (``--``). -| Here we can see that ``.dropdown {}`` is the Block; it is the sole - root of a -| discrete entity. ``.dropdown-item {}`` is an Element; it is a smaller - part of the -| ``.dropdown {}`` Block. Finally, ``.dropdown--active {}`` is a - Modifier; it is a -| specific variant of the ``.dropdown {}`` Block. +Here we can see that ``.dropdown {}`` is the Block; it is the sole root of a discrete entity. ``.dropdown-item {}`` is an Element; it is a smaller part of the ``.dropdown {}`` Block. Finally, ``.dropdown--active {}`` is a Modifier; it is a specific variant of the ``.dropdown {}`` Block. Starting Context ^^^^^^^^^^^^^^^^ -| Your Block context starts at the most logical, self-contained, - discrete -| location. To continue with our dropdown-based analogy, we’d not have a - class -| like ``.header-dropdown {}``, as the header is another, much higher - context. We’d -| probably have separate Blocks, like so: +Your Block context starts at the most logical, self-contained, discrete location. To continue with our dropdown-based analogy, we’d not have a class like ``.header-dropdown {}``, as the header is another, much higher context. We’d probably have separate Blocks, like so: .. code:: css @@ -109,15 +77,9 @@ Starting Context .dropdown-item { } -| If we did want to denote a ``.dropdown {}`` inside a ``.header {}``, - it is more -| correct to use a selector like ``.header .dropdown {}`` which bridges - two Blocks -| than it is to increase the scope of existing Blocks and Elements. +If we did want to denote a ``.dropdown {}`` inside a ``.header {}``, it is more correct to use a selector like ``.header .dropdown {}`` which bridges two Blocks than it is to increase the scope of existing Blocks and Elements. -| A more realistic example of properly scoped blocks might look - something like -| this, where each chunk of code represents its own Block: +A more realistic example of properly scoped blocks might look something like this, where each chunk of code represents its own Block: .. code:: css @@ -143,95 +105,35 @@ Incorrect notation for this would be: .page-copyright { } -| It is important to know when BEM scope starts and stops. As a rule, - BEM applies -| to self-contained, discrete parts of the UI. +It is important to know when BEM scope starts and stops. As a rule, BEM applies to self-contained, discrete parts of the UI. More Layers ^^^^^^^^^^^ -| If we were to add another Element—called, let’s say, - ``.dropdown-link {}``—to -| this ``.dropdown {}`` component, we would not need to step through - every layer of -| the DOM. That is to say, the correct notation would be - ``.dropdown-link {}``, and -| not ``.dropdown-item-link {}``. Your classes do not reflect the full - paper-trail -| of the DOM. +If we were to add another Element—called, let’s say, ``.dropdown-link {}``—to this ``.dropdown {}`` component, we would not need to step through every layer of the DOM. That is to say, the correct notation would be ``.dropdown-link {}``, and not ``.dropdown-item-link {}``. Your classes do not reflect the full paper-trail of the DOM. Layer Namespacing ~~~~~~~~~~~~~~~~~ -| There are a number of common problems when working with CSS at scale, - but the -| major two that namespacing aims to solve are clarity and confidence: - -- **Clarity:** How much information can we glean from the smallest - possible source? Is our code self-documenting? Can we make safe - assumptions from a single context? How much do we have to rely on - external or supplementary information in order to learn about a - system? -- **Confidence:** Do we have enough knowledge about a system to be able - to safely interface with it? Do we know enough about our code to be - able to confidently make changes? Do we have a way of knowing the - potential side effects of making a change? Do we have a way of - knowing what we might be able to remove? - -| This gets further complicated when dealing with -| `ITCSS`_. Knowing what layer a -| class is coming from is not always apparent. To combat this and - provide complete -| transparency we use layer based namespacing. - -| In no particular order, here are the individual namespaces and a brief -| description. We’ll look at each in more detail in a moment, but the - following -| list should acquaint you. - -- ``o-``: Signify that something is an Object, and that it may be used - in any number of unrelated contexts to the one you can currently see - it in. Making modifications to these types of class could potentially - have knock-on effects in a lot of other unrelated places. Tread - carefully. -- ``c-``: Signify that something is a Component. This is a concrete, - implementation-specific piece of UI. All of the changes you make to - its styles should be detectable in the context you’re currently - looking at. Modifying these styles should be safe and have no side - effects. -- ``u-``: Signify that this class is a Utility class. It has a very - specific role (often providing only one declaration) and should not - be bound onto or changed. It can be reused and is not tied to any - specific piece of UI. You will probably recognize this namespace from - libraries and methodologies like `SUITcss`_. -- ``t-``: Signify that a class is responsible for adding a Theme to a - view. It lets us know that UI Components’ current cosmetic appearance - may be due to the presence of a theme. Vastly improves templating for - large projects -- ``s-``: Signify that a class creates a new styling context or Scope. - Similar to a Theme, but not necessarily cosmetic, these should be - used sparingly—they can be open to abuse and lead to poor CSS if not - used wisely. -- ``is-``, ``has-``: Signify that the piece of UI in question is - currently styled a certain way because of a state or condition. This - stateful namespace is gorgeous, and comes from `SMACSS`_. It tells us - that the DOM currently has a temporary, optional, or short-lived - style applied to it due to a certain state being invoked. -- ``_``: Signify that this class is the worst of the worst—a hack! - Sometimes, although incredibly rarely, we need to add a class in our - markup in order to force something to work. If we do this, we need to - let others know that this class is less than ideal, and hopefully - temporary (i.e. do not bind onto this). -- ``js``-: Signify that this piece of the DOM has some behavior acting - upon it, and that JavaScript binds onto it to provide that behavior. - If you’re not a developer working with JavaScript, leave these well - alone. - -| Even from this short list alone, we can see just how much more - information we -| can communicate to developers simply by placing a character or two at - the front -| of our existing classes. +There are a number of common problems when working with CSS at scale, but the major two that namespacing aims to solve are clarity and confidence: + +- **Clarity:** How much information can we glean from the smallest possible source? Is our code self-documenting? Can we make safe assumptions from a single context? How much do we have to rely on external or supplementary information in order to learn about a system? +- **Confidence:** Do we have enough knowledge about a system to be able to safely interface with it? Do we know enough about our code to be able to confidently make changes? Do we have a way of knowing the potential side effects of making a change? Do we have a way of knowing what we might be able to remove? + +This gets further complicated when dealing with `ITCSS`_. Knowing what layer a class is coming from is not always apparent. To combat this and provide complete transparency we use layer based namespacing. + +In no particular order, here are the individual namespaces and a brief description. We’ll look at each in more detail in a moment, but the following list should acquaint you. + +- ``o-``: Signify that something is an Object, and that it may be used in any number of unrelated contexts to the one you can currently see it in. Making modifications to these types of class could potentially have knock-on effects in a lot of other unrelated places. Tread carefully. +- ``c-``: Signify that something is a Component. This is a concrete, implementation-specific piece of UI. All of the changes you make to its styles should be detectable in the context you’re currently looking at. Modifying these styles should be safe and have no side effects. +- ``u-``: Signify that this class is a Utility class. It has a very specific role (often providing only one declaration) and should not be bound onto or changed. It can be reused and is not tied to any specific piece of UI. You will probably recognize this namespace from libraries and methodologies like `SUITcss`_. +- ``t-``: Signify that a class is responsible for adding a Theme to a view. It lets us know that UI Components’ current cosmetic appearance may be due to the presence of a theme. Vastly improves templating for large projects +- ``s-``: Signify that a class creates a new styling context or Scope. Similar to a Theme, but not necessarily cosmetic, these should be used sparingly—they can be open to abuse and lead to poor CSS if not used wisely. +- ``is-``, ``has-``: Signify that the piece of UI in question is currently styled a certain way because of a state or condition. This stateful namespace is gorgeous, and comes from `SMACSS`_. It tells us that the DOM currently has a temporary, optional, or short-lived style applied to it due to a certain state being invoked. +- ``_``: Signify that this class is the worst of the worst—a hack! Sometimes, although incredibly rarely, we need to add a class in our markup in order to force something to work. If we do this, we need to let others know that this class is less than ideal, and hopefully temporary (i.e. do not bind onto this). +- ``js``-: Signify that this piece of the DOM has some behavior acting upon it, and that JavaScript binds onto it to provide that behavior. If you’re not a developer working with JavaScript, leave these well alone. + +Even from this short list alone, we can see just how much more information we can communicate to developers simply by placing a character or two at the front of our existing classes. Further Reading ''''''''''''''' @@ -241,41 +143,24 @@ Further Reading JavaScript Hooks ~~~~~~~~~~~~~~~~ -| As a rule, it is unwise to bind your CSS and your JS onto the same - class in -| your HTML. This is because doing so means you can’t have (or remove) - one -| without (removing) the other. It is much cleaner, much more - transparent, and -| much more maintainable to bind your JS onto specific classes. +As a rule, it is unwise to bind your CSS and your JS onto the same class in your HTML. This is because doing so means you can’t have (or remove) one without (removing) the other. It is much cleaner, much more transparent, and much more maintainable to bind your JS onto specific classes. -| I have known occasions before when trying to refactor some CSS has - unwittingly -| removed JS functionality because the two were tied to each other—it - was -| impossible to have one without the other. +I have known occasions before when trying to refactor some CSS has unwittingly removed JS functionality because the two were tied to each other—it was impossible to have one without the other. Typically, these are classes that are prepended with ``js-``, for - example: + +example: .. code:: html - <input type="submit" class="btn js-btn" value="Follow" /> + <input type="submit" class="btn js-btn" value="Follow" /> -| This means that we can have an element elsewhere which can carry with - style of -| ``.btn {}``, but without the behavior of ``.js-btn``. +This means that we can have an element elsewhere which can carry with style of ``.btn {}``, but without the behavior of ``.js-btn``. ``data-*`` Attributes ^^^^^^^^^^^^^^^^^^^^^ -| A common practice is to use ``data-*`` attributes as JS hooks, but - this is -| incorrect. ``data-*`` attributes, as per the spec, are used to store - custom -| data private to the page or application’\* (emphasis Harry Roberts). - ``data-*`` -| attributes are designed to store data, not be bound to. +A common practice is to use ``data-*`` attributes as JS hooks, but this is incorrect. ``data-*`` attributes, as per the spec, are used to store custom data private to the page or application’\* (emphasis Harry Roberts). ``data-*`` attributes are designed to store data, not be bound to. .. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 .. _SUITcss: https://suitcss.github.io/ From 6121dc6b9f14e5d1988a3c81a25aba818439a362 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 5 Oct 2017 03:03:47 -0400 Subject: [PATCH 17/98] fix spacing for selectors --- development/development/css_selectors.rst | 343 ++++------------------ 1 file changed, 62 insertions(+), 281 deletions(-) diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst index 3abe1670..9e593c6a 100644 --- a/development/development/css_selectors.rst +++ b/development/development/css_selectors.rst @@ -1,43 +1,18 @@ CSS Selectors ------------- -| Perhaps somewhat surprisingly, one of the most fundamental, critical - aspects of -| writing maintainable and scalable CSS is selectors. Their specificity, - their -| portability, and their reusability all have a direct impact on the - mileage we -| will get out of our CSS, and the headaches it might bring us. +Perhaps somewhat surprisingly, one of the most fundamental, critical aspects of writing maintainable and scalable CSS is selectors. Their specificity, their portability, and their reusability all have a direct impact on the mileage we will get out of our CSS, and the headaches it might bring us. Selector Intent ~~~~~~~~~~~~~~~ -| It is important when writing CSS that we scope our selectors - correctly, and that -| we’re selecting the right things for the right reasons. Selector - Intent is the -| process of deciding and defining what you want to style and how you - will go -| about selecting it. For example, if you are wanting to style your - website’s main -| navigation menu, a selector like this would be incredibly unwise: +It is important when writing CSS that we scope our selectors correctly, and that we’re selecting the right things for the right reasons. Selector Intent is the process of deciding and defining what you want to style and how you will go about selecting it. For example, if you are wanting to style your website’s main navigation menu, a selector like this would be incredibly unwise: .. code:: css header ul { } -| This selector’s intent is to style any ``ul`` inside any ``header`` - element, whereas -| our intent was to style the site’s main navigation. This is poor - Selector -| Intent: you can have any number of ``header`` elements on a page, and - they in -| turn can house any number of ``uls``, so a selector like this runs the - risk of -| applying very specific styling to a very wide number of elements. This - will -| result in having to write more CSS to undo the greedy nature of such a - selector. +This selector’s intent is to style any ``ul`` inside any ``header`` element, whereas our intent was to style the site’s main navigation. This is poor Selector Intent: you can have any number of ``header`` elements on a page, and they in turn can house any number of ``uls``, so a selector like this runs the risk of applying very specific styling to a very wide number of elements. This will result in having to write more CSS to undo the greedy nature of such a selector. A better approach would be a selector like: @@ -45,121 +20,52 @@ A better approach would be a selector like: .site-nav { } -| An unambiguous, explicit selector with good Selector Intent. We are - explicitly -| selecting the right thing for exactly the right reason. - -| Poor Selector Intent is one of the biggest reasons for headaches on - CSS -| projects. Writing rules that are far too greedy—and that apply very - specific -| treatments via very far reaching selectors—causes unexpected side - effects and -| leads to very tangled stylesheets, with selectors overstepping their - intentions -| and impacting and interfering with otherwise unrelated rulesets. - -| CSS cannot be encapsulated, it is inherently leaky, but we can - mitigate some of -| these effects by not writing such globally-operating selectors: **your - selectors should be as explicit and well reasoned as your reason for - wanting to select something.** +An unambiguous, explicit selector with good Selector Intent. We are explicitly selecting the right thing for exactly the right reason. + +Poor Selector Intent is one of the biggest reasons for headaches on CSS projects. Writing rules that are far too greedy—and that apply very specific treatments via very far reaching selectors—causes unexpected side effects and leads to very tangled stylesheets, with selectors overstepping their intentions and impacting and interfering with otherwise unrelated rulesets. + +CSS cannot be encapsulated, it is inherently leaky, but we can mitigate some of these effects by not writing such globally-operating selectors: **your selectors should be as explicit and well reasoned as your reason for wanting to select something.** Reusability ~~~~~~~~~~~ -| With a move toward a more component-based approach to constructing - UIs, the idea -| of reusability is paramount. We want the option to be able to move, - recycle, -| duplicate, and syndicate components across our projects. +With a move toward a more component-based approach to constructing UIs, the idea of reusability is paramount. We want the option to be able to move, recycle, duplicate, and syndicate components across our projects. -| To this end, we make heavy use of classes. IDs, as well as being - hugely -| over-specific, cannot be used more than once on any given page, - whereas classes -| can be reused an infinite amount of times. Everything you choose, from - the type -| of selector to its name, should lend itself toward being reused. +To this end, we make heavy use of classes. IDs, as well as being hugely over-specific, cannot be used more than once on any given page, whereas classes can be reused an infinite amount of times. Everything you choose, from the type of selector to its name, should lend itself toward being reused. Location Independence ~~~~~~~~~~~~~~~~~~~~~ -| Given the ever-changing nature of most UI projects, and the move to - more -| component-based architectures, it is in our interests not to style - things based -| on where they are, but on what they are. That is to say, our - components’ styling -| should not be reliant upon where we place them—they should remain - entirely -| location independent. +Given the ever-changing nature of most UI projects, and the move to more component-based architectures, it is in our interests not to style things based on where they are, but on what they are. That is to say, our components’ styling should not be reliant upon where we place them—they should remain entirely location independent. -| Let’s take an example of a call-to-action button that we have chosen - to style -| via the following selector: +Let’s take an example of a call-to-action button that we have chosen to style via the following selector: .. code:: css .promo a { } -| Not only does this have poor Selector Intent—it will greedily style - any and -| every link inside of a ``.promo`` to look like a button—it is also - pretty wasteful -| as a result of being so locationally dependent: we can’t reuse that - button with -| its correct styling outside of ``.promo`` because it is explicitly - tied to that -| location. A far better selector would have been: +Not only does this have poor Selector Intent—it will greedily style any and every link inside of a ``.promo`` to look like a button—it is also pretty wasteful as a result of being so locationally dependent: we can’t reuse that button with its correct styling outside of ``.promo`` because it is explicitly tied to that location. A far better selector would have been: .. code:: css .btn { } -| This single class can be reused anywhere outside of ``.promo`` and - will always -| carry its correct styling. As a result of a better selector, this - piece of UI is -| more portable, more recyclable, doesn’t have any dependencies, and has - much -| better Selector Intent. **A component shouldn’t have to live in a - certain place - to look a certain way.** +This single class can be reused anywhere outside of ``.promo`` and will always carry its correct styling. As a result of a better selector, this piece of UI is more portable, more recyclable, doesn’t have any dependencies, and has much better Selector Intent. **A component shouldn’t have to live in a certain place to look a certain way.** Portability ~~~~~~~~~~~ -| Reducing, or, ideally, removing, location dependence means that we can - move -| components around our markup more freely, but how about improving our - ability to -| move classes around components? On a much lower level, there are - changes we can -| make to our selectors that make the selectors themselves—as opposed to - the -| components they create—more portable. Take the following example: +Reducing, or, ideally, removing, location dependence means that we can move components around our markup more freely, but how about improving our ability to move classes around components? On a much lower level, there are changes we can make to our selectors that make the selectors themselves—as opposed to the components they create—more portable. Take the following example: .. code:: css input.btn { } -| This is a *qualified* selector; the leading ``input`` ties this - ruleset to only -| being able to work on ``input`` elements. By omitting this - qualification, we allow -| ourselves to reuse the ``.btn`` class on any element we choose, like - an ``a``, for -| example, or a ``button``. +This is a *qualified* selector; the leading ``input`` ties this ruleset to only being able to work on ``input`` elements. By omitting this qualification, we allow ourselves to reuse the ``.btn`` class on any element we choose, like an ``a``, for example, or a ``button``. -| Qualified selectors do not lend themselves well to being reused, and - every -| selector we write should be authored with reuse in mind. +Qualified selectors do not lend themselves well to being reused, and every selector we write should be authored with reuse in mind. -| Of course, there are times when you may want to legitimately qualify a -| selector—you might need to apply some very specific styling to a - particular -| element when it carries a certain class, for example: +Of course, there are times when you may want to legitimately qualify a selector—you might need to apply some very specific styling to a particular element when it carries a certain class, for example: .. code:: css @@ -179,9 +85,7 @@ Portability border: 1px solid; } -| This is one example where a qualified selector might be justifiable, - but I would -| still recommend an approach more like: +This is one example where a qualified selector might be justifiable, but I would still recommend an approach more like: .. code:: css @@ -201,34 +105,24 @@ Portability border: 1px solid; } -| This means that we can apply ``.error-box`` to any element, and not - just a -| ``div``—it is more reusable than a qualified selector. +This means that we can apply ``.error-box`` to any element, and not just a ``div``—it is more reusable than a qualified selector. Quasi-Qualified Selectors ^^^^^^^^^^^^^^^^^^^^^^^^^ -| One thing that qualified selectors can be useful for is signaling - where a class -| might be expected or intended to be used, for example: +One thing that qualified selectors can be useful for is signaling where a class might be expected or intended to be used, for example: .. code:: css ul.nav { } -| Here we can see that the ``.nav`` class is meant to be used on a - ``ul`` element, and -| not on a ``nav``. By using *quasi-qualified selectors* we can still - provide that -| information without actually qualifying the selector: +Here we can see that the ``.nav`` class is meant to be used on a ``ul`` element, and not on a ``nav``. By using *quasi-qualified selectors* we can still provide that information without actually qualifying the selector: .. code:: css /*ul*/.nav { } -| By commenting out the leading element, we can still leave it to be - read, but -| avoid qualifying and increasing the specificity of the selector. +By commenting out the leading element, we can still leave it to be read, but avoid qualifying and increasing the specificity of the selector. Naming ~~~~~~ @@ -238,24 +132,9 @@ As Phil Karlton once said ‘There are only two hard things in Computer Science: cache invalidation and naming things.’ -| I won’t comment on the former claim here, but the latter has plagued - me for -| years. My advice with regard to naming things in CSS is to pick a name - that is -| sensible, but somewhat ambiguous: aim for high reusability. For - example, instead -| of a class like ``.site-nav``, choose something like ``.primary-nav``; - rather than -| ``.footer-links``, favor a class like ``.sub-links``. - -| The differences in these names is that the first of each two examples - is tied to -| a very specific use case: they can only be used as the site’s - navigation or the -| footer’s links respectively. By using slightly more ambiguous names, - we can -| increase our ability to reuse these components in different - circumstances. +I won’t comment on the former claim here, but the latter has plagued me for years. My advice with regard to naming things in CSS is to pick a name that is sensible, but somewhat ambiguous: aim for high reusability. For example, instead of a class like ``.site-nav``, choose something like ``.primary-nav``; rather than ``.footer-links``, favor a class like ``.sub-links``. + +The differences in these names is that the first of each two examples is tied to a very specific use case: they can only be used as the site’s navigation or the footer’s links respectively. By using slightly more ambiguous names, we can increase our ability to reuse these components in different circumstances. To quote Nicolas Gallagher: @@ -263,31 +142,11 @@ To quote Nicolas Gallagher: has already reduced the ability of your architecture to scale or be easily put to use by other developers. -| That is to say, we should use sensible names—classes like ``.border`` - or ``.red`` -| are never advisable—but we should avoid using classes which describe - the exact -| nature of the content and/or its use cases. **Using a class name to - describe - content is redundant because content describes itself.** - -| The debate surrounding semantics has raged for years, but it is - important that -| we adopt a more pragmatic, sensible approach to naming things in order - to work -| more efficiently and effectively. Instead of focussing on ‘semantics’, - look more -| closely at sensibility and longevity—choose names based on ease of - maintenance, -| not for their perceived meaning. - -| Name things for people; they’re the only things that actually read - your classes -| (everything else merely matches them). Once again, it is better to - strive for -| reusable, recyclable classes rather than writing for specific use - cases. Let’s -| take an example: +That is to say, we should use sensible names—classes like ``.border`` or ``.red`` are never advisable—but we should avoid using classes which describe the exact nature of the content and/or its use cases. **Using a class name to describe content is redundant because content describes itself.** + +The debate surrounding semantics has raged for years, but it is important that we adopt a more pragmatic, sensible approach to naming things in order to work more efficiently and effectively. Instead of focussing on ‘semantics’,look more closely at sensibility and longevity—choose names based on ease of maintenance, not for their perceived meaning. + +Name things for people; they’re the only things that actually read your classes (everything else merely matches them). Once again, it is better to strive for reusable, recyclable classes rather than writing for specific use cases. Let’s take an example: .. code:: css @@ -311,29 +170,14 @@ To quote Nicolas Gallagher: */ .highlight-color { color: blue; } -| It is important to strike a balance between names that do not - literally describe -| the style that the class brings, but also ones that do not explicitly - describe -| specific use cases. Instead of ``.home-page-panel``, choose - ``.masthead``; instead -| of ``.site-nav``, favor ``.primary-nav``; instead of ``.btn-login``, - opt for -| ``.btn-primary``. +It is important to strike a balance between names that do not literally describe the style that the class brings, but also ones that do not explicitly describe specific use cases. Instead of ``.home-page-panel``, choose ``.masthead``; instead of ``.site-nav``, favor ``.primary-nav``; instead of ``.btn-login``, opt for ``.btn-primary``. Selector Performance ~~~~~~~~~~~~~~~~~~~~ -| A topic which is—with the quality of today’s browsers—more interesting - than it -| is important, is selector performance. That is to say, how quickly a - browser -| can match the selectors your write in CSS up with the nodes it finds - in the DOM. +A topic which is—with the quality of today’s browsers—more interesting than it is important, is selector performance. That is to say, how quickly a browser can match the selectors your write in CSS up with the nodes it finds in the DOM. -| Generally speaking, the longer a selector is (i.e. the more component - parts) -| the slower it is, for example: +Generally speaking, the longer a selector is (i.e. the more component parts) the slower it is, for example: .. code:: css @@ -345,116 +189,53 @@ Selector Performance .primary-nav { } -| This is because browsers read CSS selectors right-to-left. A browser - will read -| the first selector as +This is because browsers read CSS selectors right-to-left. A browser will read the first selector as - find all ``ul`` elements in the DOM; -- now check if they live anywhere inside an element with a class of - ``.header``; +- now check if they live anywhere inside an element with a class of ``.header``; - next check that ``.header`` class exists on a ``div`` element; -- now check that that all lives anywhere inside any elements with a - class of ``.home``; +- now check that that all lives anywhere inside any elements with a class of ``.home``; - finally, check that ``.home`` exists on a ``body`` element. -The second, in contrast, is simply a case of the browser reading find -all the elements with a class of ``.primary-nav``. - -| To further compound the problem, we are using descendant selectors - (e.g. -| ``.foo .bar {}``). The upshot of this is that a browser is required to - start with -| the rightmost part of the selector (i.e. ``.bar``) and keep looking up - the DOM -| indefinitely until it finds the next part (i.e. ``.foo``). This could - mean -| stepping up the DOM dozens of times until a match is found. - -| This is just one reason why -| **nesting with preprocessors is often a false economy**; as well as - making -| selectors unnecessarily more specific, and creating location - dependency, it -| also creates more work for the browser. - -| By using a child selector (e.g. ``.foo > .bar {}``) we can make the - process much -| more efficient, because this only requires the browser to look one - level higher -| in the DOM, and it will stop regardless of whether or not it found a - match. +The second, in contrast, is simply a case of the browser reading find all the elements with a class of ``.primary-nav``. + +To further compound the problem, we are using descendant selectors (e.g. ``.foo .bar {}``). The upshot of this is that a browser is required to start with the rightmost part of the selector (i.e. ``.bar``) and keep looking up the DOM indefinitely until it finds the next part (i.e. ``.foo``). This could mean stepping up the DOM dozens of times until a match is found. + +This is just one reason why **nesting with preprocessors is often a false economy**; as well as making selectors unnecessarily more specific, and creating location dependency, it also creates more work for the browser. + +By using a child selector (e.g. ``.foo > .bar {}``) we can make the process much more efficient, because this only requires the browser to look one level higher in the DOM, and it will stop regardless of whether or not it found a match. The Key Selector ^^^^^^^^^^^^^^^^ -| Because browsers read selectors right-to-left, the rightmost selector - is often -| critical in defining a selector’s performance: this is called the key - selector. +Because browsers read selectors right-to-left, the rightmost selector is often critical in defining a selector’s performance: this is called the key selector. -| The following selector might appear to be highly performant at first - glance. It -| uses an ID which is nice and fast, and there can only ever be one on a - page, so -| surely this will be a nice and speedy lookup—just find that one ID and - then -| style everything inside of it: +The following selector might appear to be highly performant at first glance. It uses an ID which is nice and fast, and there can only ever be one on a page, so surely this will be a nice and speedy lookup—just find that one ID and then style everything inside of it: .. code:: css #foo * { } -| The problem with this selector is that the key selector (``*``) is - very, very far -| reaching. What this selector actually does is find every single node - in the DOM -| (even ``<title>``, ``<link>``, and ``<head>`` elements; everything) - and then looks to -| see if it lives anywhere at any level within #foo. This is a very, - very -| expensive selector, and should most likely be avoided or rewritten. - -| Thankfully, by writing selectors with good -| Selector Intent, we are probably -| avoiding inefficient selectors by default; we are very unlikely to - have greedy -| key selectors if we’re targeting the right things for the right - reason. - -| That said, however, CSS selector performance should be fairly low on - your list -| of things to optimize; browsers are fast, and are only ever getting - faster, and -| it is only on notable edge cases that inefficient selectors would be - likely to -| pose a problem. - -| As well as their own specific issues, nesting, qualifying, and poor - Selector -| Intent all contribute to less efficient selectors. +The problem with this selector is that the key selector (``*``) is very, very far reaching. What this selector actually does is find every single node in the DOM (even ``<title>``, ``<link>``, and ``<head>`` elements; everything) and then looks to see if it lives anywhere at any level within #foo. This is a very, very expensive selector, and should most likely be avoided or rewritten. + +Thankfully, by writing selectors with good Selector Intent, we are probably avoiding inefficient selectors by default; we are very unlikely to have greedy key selectors if we’re targeting the right things for the right reason. + +That said, however, CSS selector performance should be fairly low on your list of things to optimize; browsers are fast, and are only ever getting faster, and it is only on notable edge cases that inefficient selectors would be likely to pose a problem. + +As well as their own specific issues, nesting, qualifying, and poor Selector Intent all contribute to less efficient selectors. General Rules ~~~~~~~~~~~~~ -| Your selectors are fundamental to writing good CSS. To very briefly - sum up the -| above sections: - -- **Select what you want explicitly**, rather than relying on - circumstance or coincidence. Good Selector Intent will rein in the - reach and leak of your styles. -- **Write selectors for reusability**, so that you can work more - efficiently and reduce waste and repetition. -- **Do not nest selectors unnecessarily**, because this will increase - specificity and affect where else you can use your styles. -- **Do not qualify selectors unnecessarily**, as this will impact the - number of different elements you can apply styles to. -- **Keep selectors as short as possible**, in order to keep specificity - down and performance up. - -| Focussing on these points will keep your selectors a lot more sane and - easy to -| work with on changing and long-running projects. +Your selectors are fundamental to writing good CSS. To very briefly sum up the above sections: + +- **Select what you want explicitly**, rather than relying on circumstance or coincidence. Good Selector Intent will rein in the reach and leak of your styles. +- **Write selectors for reusability**, so that you can work more efficiently and reduce waste and repetition. +- **Do not nest selectors unnecessarily**, because this will increase specificity and affect where else you can use your styles. +- **Do not qualify selectors unnecessarily**, as this will impact the number of different elements you can apply styles to. +- **Keep selectors as short as possible**, in order to keep specificity down and performance up. + +Focussing on these points will keep your selectors a lot more sane and easy to work with on changing and long-running projects. Further Reading ''''''''''''''' From ef8b50957b8906a6a5dac18fef1e4645f3a60be3 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Thu, 5 Oct 2017 11:34:55 -0400 Subject: [PATCH 18/98] update remaining docs spacing --- development/development/css_architecture.rst | 793 ------------------- development/development/css_specificity.rst | 341 ++------ development/development/css_standards.rst | 272 ++----- 3 files changed, 151 insertions(+), 1255 deletions(-) delete mode 100644 development/development/css_architecture.rst diff --git a/development/development/css_architecture.rst b/development/development/css_architecture.rst deleted file mode 100644 index 7a26440d..00000000 --- a/development/development/css_architecture.rst +++ /dev/null @@ -1,793 +0,0 @@ -Architectural Principles ------------------------- - -| You would be forgiven for thinking that an architecture for CSS is a - somewhat -| grandiose and unnecessary concept: why would something so simple, so -| straightforward, need something as complex or considered as an - architecture?! - -| Well, as we’ve seen, CSS’ simplicity, its looseness, and its unruly - nature mean -| that the best way of managing (reading, taming) it at any reasonable - scale is -| through a strict and specific architecture. A solid architecture can - help us -| control our specificity, enforce naming conventions, manage our source - order, -| create a sane development environment, and generally make managing our - CSS -| projects a lot more consistent and comfortable. - -| There is no tool, no preprocessor, no magic bullet, that will make - your CSS -| better on its own: a developer’s best tool when working with such a - loose -| syntax is self-discipline, conscientiousness, and diligence, and a - well-defined -| architecture will help enforce and facilitate these traits. - -| Architectures are large, overarching, principle-led collections of - smaller -| conventions which come together to provide a managed environment in - which code -| is written and maintained. Architectures are typically quite high - level, and -| leave implementation details—such as naming conventions or syntax and -| formatting, for example—to the team implementing it. - -| Most architectures are usually based around existing design patterns - and -| paradigms, and, more often than not, these paradigms were born of - computer -| scientists and software engineers. For all CSS isn’t ‘code’, and - doesn’t -| exhibit many traits that programming languages do, we find that we can - apply -| some of these same principles to our own work. - -| In this section, we’ll take a look at some of these design patterns - and -| paradigms, and how we can use them to reduce code—and increase code - reuse—in -| our CSS projects. - -High-level Overview -~~~~~~~~~~~~~~~~~~~ - -At a very high-level, our architecture should help you - -- provide a consistent and sane environment; -- accommodate change; -- grow and scale your codebase; -- promote reuse and efficiency; -- increased productivity. - -| Typically, this will mean a class-based and componentised - architecture, split -| up into manageable modules, probably using a preprocessor. Of course, - there is -| far more to an architecture than that, so let’s look at some - principles… - -Object-orientation -~~~~~~~~~~~~~~~~~~ - -| Object-orientation is a programming paradigm that breaks larger - programs up -| into smaller, in(ter)dependent objects that all have their own roles - and -| responsibilities. From Wikipedia: - -.. note:: - -Object-oriented programming (OOP) is a programming paradigm that -represents the concept of ‘objects’ […] which are usually instances of -classes, [and] are used to interact with one another to design -applications and computer programs. - -| When applied to CSS, we call it object-oriented CSS, or OOCSS. OOCSS - was coined -| and popularized by Nicole Sullivan, whose Media Object has become the - poster -| child of the methodology. - -| OOCSS deals with the separation of UIs into structure and skin: - breaking UI -| components into their underlying structural forms, and layering their - cosmetic -| forms on separately. This means that we can recycle common and - recurring design -| patterns very cheaply without having to necessarily recycle their - specific -| implementation details at the same time. OOCSS promotes reuse of code, - which -| makes us quicker, as well as keeping the size of our codebase down. - -| Structural aspects can be thought of like skeletons; common, recurring - frames -| that provide design-free constructs known as objects and abstractions. - Objects -| and abstractions are simple design patterns that are devoid of any - cosmetics; -| we abstract out the shared structural traits from a series of - components into a -| generic object. - -| Skin(Theme) is a layer that we (optionally) add to our structure in - order to -| give objects and abstractions a specific look-and-feel. - -Let’s look at an example: - -.. code:: css - - /** - * A simple, design-free button object. Extend this object with a `.btn--*` skin - * class. - */ - .btn { - display: inline-block; - padding: 1em 2em; - vertical-align: middle; - } - - - /** - * Positive buttons’ skin. Extends `.btn`. - */ - .btn-inverse { - background-color: green; - color: white; - } - -| Above, we can see how the ``.btn {}`` class simply provides structural - styling to -| an element, and doesn’t concern itself with any cosmetics. We - supplement the -| ``.btn {}`` object with a second class, such as ``.btn-inverse {}`` in - order to -| give that DOM node specific cosmetics: - -.. code:: html - - <button class="btn btn-inverse">Delete</button> - -| Favor the multiple-class approach over using something like - ``@extend``: using -| multiple classes in your markup—as opposed to wrapping the classes up - into one -| using a preprocessor—gives you a better paper-trail in your markup, - and allows -| you to see quickly and explicitly which classes are acting on a piece - of HTML; -| allows for greater composition in that classes are not tightly bound - to other -| styles in your CSS. Whenever you are building a UI component, try and - see if -| you can break it into two parts: one for structural styles (paddings, - layout, -| etc.) and another for skin (colors, typefaces, etc.). - -| As a rule its a reasonable practice to set defaults of all skin - classes on the -| objects and then use the modifiers to overwrite them. - -Further Reading -''''''''''''''' - -- `The media object saves hundreds of lines of code`_ -- `The flag object`_ -- `Naming UI components in OOCSS`_ - -The Single Responsibility Principle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -| The single responsibility principle is a paradigm that, very loosely, - states -| that all pieces of code (in our case, classes) should focus on doing - one thing -| and one thing only. More formally: - -.. note:: - -…the single responsibility principle states that every context -(class, function, variable, etc.) should have a single responsibility, -and that responsibility should be entirely encapsulated by the context. - -| What this means for us is that our CSS should be composed of a series - of much -| smaller classes that focus on providing very specific and limited -| functionality. This means that we need to decompose UIs into their - smallest -| component pieces that each serve a single responsibility; they all do - just one -| job, but can be very easily combined and composed to make much more - versatile -| and complex constructs. Let’s take some example CSS that does not - adhere to the -| single responsibility principle: - -.. code:: css - - .error-message { - display: block; - padding: 10px; - border-top: 1px solid #ff0000; - border-bottom: 1px solid #ff0000; - background-color: #ffeeee; - color: #ff0000; - font-weight: bold; - } - - .success-message { - display: block; - padding: 10px; - border-top: 1px solid #00ff00; - border-bottom: 1px solid #00ff00; - background-color: #eeffee; - color: #00ff00; - font-weight: bold; - } - -| Here we can see that—despite being named after one very specific - use-case—these -| classes are handling quite a lot: layout, structure, and cosmetics. We - also -| have a lot of repetition. We need to refactor this in order to - abstract out -| some shared objects (OOCSS) and bring it more inline with the single -| responsibility principle. We can break these two classes out into four - much -| smaller responsibilities: - -.. code:: css - - .box { - display: block; - padding: 10px; - } - - - .message { - border-style: solid; - border-width: 1px 0; - font-weight: bold; - } - - .message-error { - background-color: #ffeeee; - color: #ff0000; - } - - .message-success { - background-color: #eeffee; - color: #00ff00; - } - -| Now we have a general abstraction for boxes which can live, and be - used, -| completely separately from our message component, and we have a base - message -| component that can be extended by a number of smaller responsibility - classes. -| The amount of repetition has been greatly reduced, and our ability to - extend -| and compose our CSS has been greatly increased. This is a great - example of -| OOCSS and the single responsibility principle working in tandem. - -| By focussing on single responsibilities, we can give our code much - more -| flexibility, and extending components’ functions becomes very simple - when -| sticking to the open/closed principle, which we’re going to look at - next. - -Further Reading -''''''''''''''' - -- `The single responsibility principle applied to CSS`_ - -The Open/Closed Principle -~~~~~~~~~~~~~~~~~~~~~~~~~ - -| The open/closed principle, in my opinion, is rather poorly named. It - is poorly -| named because 50% of the vital information is omitted from its title. - The -| open/closed principle states that - -.. note:: - -software entities (classes, modules, functions, etc.) should be open -for extension, but closed for modification. - -| See the most important words—extension and modification—are completely - missing -| from the name, which isn’t very useful at all. - -| Once you have trained yourself to remember what the words open and - closed -| actually relate to, you’ll find that open/closed principle remarkably - simple: -| any additions, new functionality, or features we add to our classes - should be -| added via extension—we should not modify these classes directly. This - really -| trains us to write bulletproof single responsibilities: because we - shouldn’t -| modify objects and abstractions directly, we need to make sure we get - them as -| simple as possible the first time. This means that we should never - need to -| actually change an abstraction—we’d simply stop using it—but any - slight -| variants of it can be made very easily by extending it. - -Let’s take an example: - -.. code:: css - - .box { - display: block; - padding: 10px; - } - - .box-large { - padding: 20px; - } - -Here we can see that the ``.box {}`` object is incredibly simple: we’ve -stripped it right back into one very small and very focussed -responsibility. To modify that box, we extend it with another class; -``.box--large {}``. Here the ``.box {}`` class is closed to -modification, but open to being extended. - -An incorrect way of achieving the same might look like this: - -.. code:: css - - .box { - display: block; - padding: 10px; - } - - .content .box { - padding: 20px; - } - -| Not only is this overly specific, locationally dependent, and - potentially -| displaying poor Selector Intent, we are modifying the ``.box {}`` - directly. We -| should rarely—if ever—find an object or abstraction’s class as a key - selector -| in a compound selector. - -A selector like ``.content .box {}`` is potentially troublesome because - -- it forces all ``.box`` components into that style when placed inside - of ``.content``, which means the modification is dictated to - developers, whereas developers should be allowed to opt into changes - explicitly; -- the ``.box`` style is now unpredictable to developers; the single - responsibility no longer exists because nesting the selector produces - a forced caveat. - -| All modifications, additions, and changes should always be opt-in, not -| mandatory. If you think something might need a slight adjustment to - take it -| away from the norm, provide another class which adds this - functionality. - -| When working in a team environment, be sure to write API-like CSS; - always -| ensure that existing classes remain backward compatible (i.e. no - changes at -| their root) and provide new hooks to bring in new features. Changing - the root -| object, abstraction, or component could have huge knock-on effects for -| developers making use of that code elsewhere, so never modify existing - code -| directly. - -| Exceptions may present themselves when it transpires that a root - object does -| need a rewrite or refactor, but it is only in these specific cases - that you -| should modify code. Remember: **open for extension; closed for - modification.** - -Further Reading -''''''''''''''' - -- `The open/closed principle applied to CSS`_ - -DRY -~~~ - -| DRY, which stands for Don’t Repeat Repeat Yourself, is a - micro-principle used -| in software development which aims to keep the repetition of key - information to -| a minimum. Its formal definition is that - -.. note:: - -every piece of knowledge must have a single, unambiguous, -authoritative representation within a system. - -| Although a very simple principle—in principle—DRY is often - misinterpreted as -| the necessity to never repeat the exact same thing twice at all in a - project. -| This is impractical and usually counterproductive, and can lead to - forced -| abstractions, over-thought and -engineered code, and unusual - dependencies. - -| The key isn’t to avoid all repetition, but to normalize and abstract - meaningful -| repetition. If two things happen to share the same declarations - coincidentally, -| then we needn’t DRY anything out; that repetition is purely - circumstantial and -| cannot be shared or abstracted. For example: - -.. code:: css - - .btn { - font-weight: bold; - display: inline-block; - padding: 1rem 2rem; - } - - [...] - - .page-title { - font-size: 3rem; - font-weight: bold; - line-height: 1.4; - } - - [...] - - .user-profile-title { - font-size: 1.2rem; - font-weight: bold; - line-height: 1.5; - } - -| From the above code, we can reasonably deduce that the - ``font-weight: bold;`` -| declaration appears three times purely coincidentally. To try and - create an -| abstraction, mixin, or ``@extend`` directive to cater for this - repetition would -| be overkill, and would tie these three rulesets together based purely - on -| circumstance. - -| However, imagine we’re using a web-font that requires - ``font-weight: bold;`` to -| be declared every time the ``font-family`` is: - -.. code:: css - - .btn { - font-family: "My Web Font", sans-serif; - font-weight: bold; - display: inline-block; - padding: 1rem 2rem; - } - - [...] - - .page-title { - font-family: "My Web Font", sans-serif; - font-size: 3rem; - font-weight: bold; - line-height: 1.4; - } - - [...] - - .user-profile-title { - font-family: "My Web Font", sans-serif; - font-size: 1.2rem; - font-weight: bold; - line-height: 1.5; - } - -| Here we’re repeating a more meaningful snippet of CSS; these two - declarations -| have to always be declared together. In this instance, we probably - would DRY -| out our CSS. - -| I would recommend using a mixin over ``@extend`` here because, even - though the -| two declarations are thematically grouped, the rulesets themselves are - still -| separate, unrelated entities: to use ``@extend`` would be to - physically group -| these unrelated rulesets together in our CSS, thus making the - unrelated related. - -Our mixin: - -.. code:: scss - - @mixin my-web-font() { - font-family: "My Web Font", sans-serif; - font-weight: bold; - } - - .btn { - @include my-web-font(); - display: inline-block; - padding: 1rem 2rem; - } - - [...] - - .page-title { - @include my-web-font(); - font-size: 3rem; - line-height: 1.4; - } - - [...] - - .user-profile__title { - @include my-web-font(); - font-size: 1.2rem; - line-height: 1.5; - } - -| Now the two declarations only exist once, meaning we’re not repeating -| ourselves. If we ever switch out our web-font, or move to a -| ``font-weight: normal;`` version, we only need to make that change in - one place. - -| In short, only DRY code that is actually, thematically related. Do not - try to -| reduce purely coincidental repetition: -| **duplication is better than the wrong abstraction.** - -Further Reading -''''''''''''''' - -- `Writing DRYer vanilla CSS`_ - -Composition over Inheritance -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -| Now that we’re used to spotting abstractions and creating single -| responsibilities, we should be in a great position to start composing - more -| complex composites from a series of much smaller component parts. - Nicole -| Sullivan likens this to using Lego; tiny, single responsibility pieces - which -| can be combined in a number of different quantities and permutations - to create -| a multitude of very different looking results. - -| This idea of building through composition is not a new one, and is - often -| referred to as composition over inheritance. This principle suggests - that -| larger systems should be composed from much smaller, individual parts, - rather -| than inheriting behavior from a much larger, monolithic object. This - should -| keep your code decoupled—nothing inherently relies on anything else. - -| Composition is a very valuable principle for an architecture to make - use of, -| particularly considering the move toward component-based UIs. It will - mean you -| can more easily recycle and reuse functionality, as well rapidly - construct -| larger parts of UI from a known set of composeable objects. Think back - to our -| error message example in the -| Single Responsibility Principle -| section; we created a complete UI component by composing a number of - much -| smaller and unrelated objects. - -The Separation of Concerns -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -| The separation of concerns is a principle which, at first, sounds a - lot like -| the single responsibility principle. The separation of concerns states - that -| code should be broken up - -.. note:: - -into distinct sections, such that each section addresses a separate -concern. A concern is a set of information that affects the code of a -computer program. A program that embodies SoC well is called a modular -program. - -| Modular is a word we’re probably used to; the idea of breaking UIs and - CSS into -| much smaller, composeable pieces. The separation of concerns is just a - formal -| definition which covers the concepts of modularity and encapsulation - in code. -| In CSS this means building individual components, and writing code - which only -| focusses itself on one task at a time. - -The term was coined by Edsger W. Dijkstra, who rather elegantly said: - -.. note:: - -Let me try to explain to you, what to my taste is characteristic for -all intelligent thinking. It is, that one is willing to study in depth -an aspect of one’s subject matter in isolation for the sake of its own -consistency, all the time knowing that one is occupying oneself only -with one of the aspects. We know that a program must be correct and we -can study it from that viewpoint only; we also know that it should be -efficient and we can study its efficiency on another day, so to speak. -In another mood we may ask ourselves whether, and if so: why, the -program is desirable. But nothing is gained—on the contrary!—by tackling -these various aspects simultaneously. It is what I sometimes have called -‘the separation of concerns’, which, even if not perfectly possible, is -yet the only available technique for effective ordering of one’s -thoughts, that I know of. This is what I mean by ‘focusing one’s -attention upon some aspect’: it does not mean ignoring the other -aspects, it is just doing justice to the fact that from this aspect’s -point of view, the other is irrelevant. It is being one- and -multiple-track minded simultaneously. - -| Beautiful. The idea here is to focus fully on one thing at once; build - one -| thing to do its job very well whilst paying as little attention as - possible to -| other facets of your code. Once you have addressed and built all these - separate -| concerns in isolation—meaning they’re probably very modular, - decoupled, and -| encapsulated—you can begin bringing them together into a larger - project. - -| A great example is layout. If you are using a grid system, all of the - code -| pertaining to layout should exist on its own, without including - anything else. -| You’ve written code that handles layout, and that’s it: - -.. code:: html - - <div class="layout"> - - <div class="layout-item two-thirds"> - </div> - - <div class="layout-item one-third"> - </div> - - </div> - -| You will now need to write new, separate code to handle what lives - inside of -| that layout: - -.. code:: html - - <div class="layout"> - - <div class="layout-item two-thirds"> - <section class="content"> - ... - </section> - </div> - - <div class="layout-item one-third"> - <section class="sub-content"> - ... - </section> - </div> - - </div> - -| The separation of concerns allows you to keep code self-sufficient, - ignorant, -| and ultimately a lot more maintainable. Code which adheres to the - separation of -| concerns can be much more confidently modified, edited, extended, and -| maintained because we know how far its responsibilities reach. We know - that -| modifying layout, for example, will only ever modify layout—nothing - else. - -| The separation of concerns increases reusability and confidence whilst - reducing -| dependency. - -Misconceptions -^^^^^^^^^^^^^^ - -| There are, I feel, a number of unfortunate misconceptions surrounding - the -| separation of concerns when applied to HTML and CSS. They all seem to - revolve -| around some format of: - -.. note:: - -Using classes for CSS in your markup breaks the separation of -concerns. - -| Unfortunately, this is simply not true. The separation of concerns - does exist -| in the context of HTML and CSS (and JS), but not in the way a lot of - people -| seem to believe. - -| The separation of concerns when applied to front-end code is not about -| classes-in-HTML-purely-for-styling-hooks-blurring-the-lines-between-concerns; -| it is about the very fact that we are using different languages for - markup and -| styling at all. - -| Back before CSS was widely adopted, we’d use ``tables`` to lay content - out, and -| ``font`` elements with ``color`` attributes to provide cosmetic - styling. The -| problem here is that HTML was being used to create content and also to - style -| it; there was no way of having one without the other. This was a - complete lack -| of separation of concerns, which was a problem. CSS’ job was to - provide a -| completely new syntax to apply this styling, allowing us to separate - our -| content and style concerns across two technologies. - -Another common argument is that *‘putting classes in your HTML puts -style information in your markup’*. - -| So, in a bid to circumvent this, people adopt selectors that might - look a -| little like this: - -.. code:: css - - body > header:first-of-type > nav > ul > li > a { - } - -| This CSS—presumably to style our site’s main nav—has the usual - problems of -| location dependency, poor Selector Intent, and high specificity, but - it also -| manages to do exactly what *developers* are trying to avoid, only in - the -| opposite direction: **it puts DOM information in your CSS**. - Aggressive -| attempts to avoid putting any style hints or hooks in markup only lead - to -| overloading stylesheets with DOM information. - -| In short: having classes in your markup does not violate the - separation of -| concerns. Classes merely act as an API to link two separate concerns - together. -| The simplest way to separate concerns is to write well formed HTML and - well -| formed CSS, and link to two together with sensible, judicious use of - classes. - -.. _The media object saves hundreds of lines of code: http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code/ -.. _The flag object: http://csswizardry.com/2013/05/the-flag-object/ -.. _Naming UI components in OOCSS: http://csswizardry.com/2014/03/naming-ui-components-in-oocss/ -.. _The single responsibility principle applied to CSS: http://csswizardry.com/2012/04/the-single-responsibility-principle-applied-to-css/ -.. _The open/closed principle applied to CSS: http://csswizardry.com/2012/06/the-open-closed-principle-applied-to-css/ -.. _Writing DRYer vanilla CSS: http://csswizardry.com/2013/07/writing-dryer-vanilla-css/ diff --git a/development/development/css_specificity.rst b/development/development/css_specificity.rst index f776b045..31493684 100644 --- a/development/development/css_specificity.rst +++ b/development/development/css_specificity.rst @@ -1,37 +1,17 @@ Specificity ----------- -| As we’ve seen, CSS isn’t the most friendly of languages: globally - operating, -| very leaky, dependent on location, hard to encapsulate, based on - inheritance… -| But! None of that even comes close to the horrors of specificity. - -| No matter how well considered your naming, regardless of how perfect - your -| source order and cascade are managed, and how well you’ve scoped your - rulesets, -| just one overly-specific selector can undo everything. It is a - gigantic -| curveball, and undermines CSS’ very nature of the cascade, - inheritance, and -| source order. - -| The problem with specificity is that it sets precedents and trumps - that cannot -| simply be undone. If we take the following example +As we’ve seen, CSS isn’t the most friendly of languages: globally operating, very leaky, dependent on location, hard to encapsulate, based on inheritance… But! None of that even comes close to the horrors of specificity. + +No matter how well considered your naming, regardless of how perfect your source order and cascade are managed, and how well you’ve scoped your rulesets, just one overly-specific selector can undo everything. It is a gigantic curveball, and undermines CSS’ very nature of the cascade, inheritance, and source order. + +The problem with specificity is that it sets precedents and trumps that cannot simply be undone. If we take the following example .. code:: css #content table { } -| Not only does this exhibit poor -| **Selector Intent**, we didn’t actually -| want every ``table`` in the ``#content`` area. We wanted a specific - type of ``table`` -| that just happened to live there. This is a hugely over-specific - selector. It -| becomes apparent, when we needed a second type of ``table``: +Not only does this exhibit poor **Selector Intent**, we didn’t actually want every ``table`` in the ``#content`` area. We wanted a specific type of ``table`` that just happened to live there. This is a hugely over-specific selector. It becomes apparent, when we needed a second type of ``table``: .. code:: css @@ -42,20 +22,12 @@ Specificity */ .my-new-table { } -| The first selector was trumping the specificity of the one defined - after it, -| working against CSS’ source-order based application of styles. In - order to -| remedy this, we have two main options. we could +The first selector was trumping the specificity of the one defined after it, working against CSS’ source-order based application of styles. In order to remedy this, we have two main options. we could #. refactor the CSS and HTML to remove that ID; #. write a more specific selector to override it. -| Unfortunately, refactoring would take a long time in a mature product - and the -| knock-on effects of removing this ID would be more substantial - business cost -| than the second option: just write a more specific selector. +Unfortunately, refactoring would take a long time in a mature product and the knock-on effects of removing this ID would be more substantial business cost than the second option: just write a more specific selector. .. code:: css @@ -63,53 +35,26 @@ Specificity #content .my-new-table { } -| Now we have a selector that is even more specific still! And if we - ever want to -| override this one, we will need another selector of at least the same -| specificity defined after it. We’ve started on a downward spiral. +Now we have a selector that is even more specific still! And if we ever want to override this one, we will need another selector of at least the same specificity defined after it. We’ve started on a downward spiral. Specificity can, among other things, - limit your ability to extend and manipulate a codebase; - interrupt and undo CSS’ cascading, inheriting nature; - cause avoidable verbosity in your project; -- prevent things from working as expected when moved into different - environments; +- prevent things from working as expected when moved into different environments; - lead to serious developer frustration. -| All of these issues are greatly magnified when working on a larger - project with -| a number of developers contributing code. +All of these issues are greatly magnified when working on a larger project with a number of developers contributing code. Keep It Low at All Times ~~~~~~~~~~~~~~~~~~~~~~~~ -| The problem with specificity isn’t necessarily that it’s high or low; - it’s the -| fact it is so variant and that it cannot be opted out of: the only way - to deal -| with it is to get progressively more specific—the notorious - specificity wars we -| looked at above. - -| One of the single, simplest tips for an easier life when writing CSS, -| particularly at any reasonable scale—is to always try to keep - specificity as -| low as possible at all times. Try to make sure there isn’t a lot of - variance -| between selectors in the codebase, and that all selectors strive for - as low a -| specificity as possible. - -| Doing so will instantly help us tame and manage the project, meaning - that no -| overly-specific selectors are likely to impact or affect anything of a - lower -| specificity elsewhere. It also means we’re less likely to need to - fight our way -| out of specificity corners, and we’ll probably also be writing much - smaller -| stylesheets. +The problem with specificity isn’t necessarily that it’s high or low; it’s the fact it is so variant and that it cannot be opted out of: the only way to deal with it is to get progressively more specific—the notorious specificity wars we looked at above. + +One of the single, simplest tips for an easier life when writing CSS, particularly at any reasonable scale—is to always try to keep specificity as low as possible at all times. Try to make sure there isn’t a lot of variance between selectors in the codebase, and that all selectors strive for as low a specificity as possible. + +Doing so will instantly help us tame and manage the project, meaning that no overly-specific selectors are likely to impact or affect anything of a lower specificity elsewhere. It also means we’re less likely to need to fight our way out of specificity corners, and we’ll probably also be writing much smaller stylesheets. Simple changes to the way we work include, but are not limited to, @@ -118,71 +63,41 @@ Simple changes to the way we work include, but are not limited to, - not qualifying classes; - not chaining selectors. -**Specificity can be wrangled and understood, but it is safer just to -avoid it entirely.** +**Specificity can be wrangled and understood, but it is safer just to avoid it entirely.** IDs in CSS ~~~~~~~~~~ -| If we want to keep specificity low, which we do, we have one really - quick-win, -| simple, easy-to-follow rule that we can employ to help us: +If we want to keep specificity low, which we do, we have one really quick-win, simple, easy-to-follow rule that we can employ to help us: .. warning:: **NEVER USE IDs in CSS** -| Not only are IDs inherently non-reusable, they are also vastly more - specific -| than any other selector, and therefore become specificity anomalies. - Where the -| rest of your selectors are relatively low specificity, your ID-based - selectors -| are, comparatively, much, much higher. +Not only are IDs inherently non-reusable, they are also vastly more specific than any other selector, and therefore become specificity anomalies. Where the rest of your selectors are relatively low specificity, your ID-based selectors are, comparatively, much, much higher. -| In fact, to highlight the severity of this difference, see how one - thousand -| chained classes cannot override the specificity of a single ID: -| `jsfiddle.net/0yb7rque`_. +In fact, to highlight the severity of this difference, see how one thousand chained classes cannot override the specificity of a single ID: `jsfiddle.net/0yb7rque`_. .. warning:: -(Please note that in Firefox you may see the text rendering in blue: -this is a `known bug`_, and an ID will be overridden by 256 chained -classes.) +(Please note that in Firefox you may see the text rendering in blue: this is a `known bug`_, and an ID will be overridden by 256 chained classes.) .. note:: -**N.B.** It is still perfectly okay to use IDs in HTML and -JavaScript; it is only in CSS that they prove troublesome. +**N.B.** It is still perfectly okay to use IDs in HTML and JavaScript; it is only in CSS that they prove troublesome. -| It is often suggested that developers who choose not to use IDs in CSS - merely -| don’t understand how specificity works. This is as incorrect as it is -| offensive: no matter how experienced a developer you are, this - behavior cannot -| be circumvented; no amount of knowledge will make an ID less specific. +It is often suggested that developers who choose not to use IDs in CSS merely don’t understand how specificity works. This is as incorrect as it is offensive: no matter how experienced a developer you are, this behavior cannot be circumvented; no amount of knowledge will make an ID less specific. -| Opting into this way of working only introduces the chance of problems -| occurring further down the line, and—particularly when working at - scale—all -| efforts should be made to avoid the potential for problems to arise. - In a -| sentence: +Opting into this way of working only introduces the chance of problems occurring further down the line, and—particularly when working at scale—all efforts should be made to avoid the potential for problems to arise. In a sentence: **It is just not worth introducing the risk.** Nesting ~~~~~~~ -| We’ve already looked at how nesting can lead to location dependent and -| potentially inefficient code, but now it’s time to take a look at - another of -| its pitfalls: it makes selectors more specific. +We’ve already looked at how nesting can lead to location dependent and potentially inefficient code, but now it’s time to take a look at another of its pitfalls: it makes selectors more specific. -| When we talk about nesting, we don’t necessarily mean preprocessor - nesting, -| like so: +When we talk about nesting, we don’t necessarily mean preprocessor nesting, like so: .. code:: scss @@ -193,10 +108,7 @@ Nesting } -| We’re actually talking about descendant or child selectors; selectors - which -| rely on a thing within a thing. That could look like any one of the - following: +We’re actually talking about descendant or child selectors; selectors which rely on a thing within a thing. That could look like any one of the following: .. code:: css @@ -220,19 +132,11 @@ Nesting */ nav ul li { } -| Whether you arrive at this CSS via a preprocessor or not isn’t - particularly -| important, but it is worth noting **that preprocessors tout this as a - feature, where it is actually to be avoided wherever possible.** +Whether you arrive at this CSS via a preprocessor or not isn’t particularly important, but it is worth noting **that preprocessors tout this as a feature, where it is actually to be avoided wherever possible.** -| Generally speaking, each part in a compound selector adds specificity. - Ergo, -| the fewer parts to a compound selector then the lower its overall - specificity, -| and we always want to keep specificity low. To quote Jonathan Snook: +Generally speaking, each part in a compound selector adds specificity. Ergo, the fewer parts to a compound selector then the lower its overall specificity, and we always want to keep specificity low. To quote Jonathan Snook: - …whenever declaring your styles, **use the least number of selectors - required to style an element.** + …whenever declaring your styles, **use the least number of selectors required to style an element.** Let’s look at an example: @@ -246,13 +150,7 @@ Let’s look at an example: color: red; } -| To style an element with a class of ``.widget-title``, we have a - selector that -| is twice as specific as it needs to be. That means that if we want to - make any -| modifications to ``.widget-title``, we’ll need another - at-least-equally specific -| selector: +To style an element with a class of ``.widget-title``, we have a selector that is twice as specific as it needs to be. That means that if we want to make any modifications to ``.widget-title``, we’ll need another at-least-equally specific selector: .. code:: css @@ -264,41 +162,20 @@ Let’s look at an example: color: blue; } -| Not only is this entirely avoidable—we caused this problem - ourselves—we have a -| selector that is literally double the specificity it needs to be. We - used 200% -| of the specificity actually required. And not only that, but this also - leads to -| needless verbosity in our code—more to send over the wire. +Not only is this entirely avoidable—we caused this problem ourselves—we have a selector that is literally double the specificity it needs to be. We used 200% of the specificity actually required. And not only that, but this also leads to needless verbosity in our code—more to send over the wire. .. warning:: -As a rule, **if a selector will work without it being nested then do -not nest it.** +As a rule, **if a selector will work without it being nested then do not nest it.** Scope ~~~~~ -| One possible advantage of nesting—which, unfortunately, does not - outweigh the -| disadvantages of increased specificity—is that it provides us with a - namespace -| of sorts. A selector like ``.widget .title`` scopes the styling of - ``.title`` to an -| element that only exists inside of an element carrying a class of - ``.widget``. - -| This goes some way to providing our CSS with scope and encapsulation, - but does -| still mean that our selectors are twice as specific as they need to - be. A -| better way of providing this scope would be via a namespace—which does - not lead -| to an unnecessary increase in specificity. - -Now we have better scoped CSS with minimal specificity—the best of both -worlds. +One possible advantage of nesting—which, unfortunately, does not outweigh the disadvantages of increased specificity—is that it provides us with a namespace of sorts. A selector like ``.widget .title`` scopes the styling of ``.title`` to an element that only exists inside of an element carrying a class of ``.widget``. + +This goes some way to providing our CSS with scope and encapsulation, but does still mean that our selectors are twice as specific as they need to be. A better way of providing this scope would be via a namespace—which does not lead to an unnecessary increase in specificity. + +Now we have better scoped CSS with minimal specificity—the best of both worlds. Further Reading ''''''''''''''' @@ -308,41 +185,19 @@ Further Reading ``!important`` ~~~~~~~~~~~~~~ -| The word ``!important`` sends shivers down the spines of almost all - front-end -| developers. ``!important`` is a direct manifestation of problems with -| specificity; it is a way of cheating your way out of specificity wars, - but -| usually comes at a heavy price. It is often viewed as a last resort—a -| desperate, defeated stab at patching over the symptoms of a much - bigger problem -| with your code. +The word ``!important`` sends shivers down the spines of almost all front-end developers. ``!important`` is a direct manifestation of problems with specificity; it is a way of cheating your way out of specificity wars, but usually comes at a heavy price. It is often viewed as a last resort—a desperate, defeated stab at patching over the symptoms of a much bigger problem with your code. -| The general rule is that ``!important`` is always a bad thing, but, to - quote -| Jamie Mason: +The general rule is that ``!important`` is always a bad thing, but, to quote Jamie Mason: Rules are the children of principles. -| That is to say, a single rule is a simple, black-and-white way of - adhering to a -| much larger principle. When you’re starting out, the rule never use -| ``!important`` is a good one. +That is to say, a single rule is a simple, black-and-white way of adhering to a much larger principle. When you’re starting out, the rule never use ``!important`` is a good one. -| However, once you begin to grow and mature as a developer, you begin - to -| understand that the principle behind that rule is simply about keeping -| specificity low. You’ll also learn when and where the rules can be - bent… +However, once you begin to grow and mature as a developer, you begin to understand that the principle behind that rule is simply about keeping specificity low. You’ll also learn when and where the rules can be bent… -| ``!important`` does have a place in CSS projects, but only if used - sparingly and -| proactively. +``!important`` does have a place in CSS projects, but only if used sparingly and proactively. -| Proactive use of ``!important`` is when it is used *before* you’ve - encountered -| any specificity problems; when it is used as a guarantee rather than - as a fix. +Proactive use of ``!important`` is when it is used *before* you’ve encountered any specificity problems; when it is used as a guarantee rather than as a fix. For example: @@ -356,28 +211,11 @@ For example: display: none !important; } -| These two helper, or *utility*, classes are very specific in their - intentions: -| you would only use them if you wanted something to be rendered at 50% - width or -| not rendered at all. If you didn’t want this behavior, you would not - use these -| classes, therefore whenever you do use them you will definitely want - them to -| win. - -| Here we proactively apply ``!important`` to ensure that these styles - always win. -| This is the correct use of ``!important`` to guarantee that these - trumps always -| work, and don’t accidentally get overridden by something else more - specific. - -| Incorrect, reactive use of ``!important`` is when it is used to combat -| specificity problems after the fact: applying ``!important`` to - declarations -| because of poorly architected CSS. For example, let’s imagine we have - this HTML: +These two helper, or *utility*, classes are very specific in their intentions: you would only use them if you wanted something to be rendered at 50% width or not rendered at all. If you didn’t want this behavior, you would not use these classes, therefore whenever you do use them you will definitely want them to win. + +Here we proactively apply ``!important`` to ensure that these styles always win. This is the correct use of ``!important`` to guarantee that these trumps always work, and don’t accidentally get overridden by something else more specific. + +Incorrect, reactive use of ``!important`` is when it is used to combat specificity problems after the fact: applying ``!important`` to declarations because of poorly architected CSS. For example, let’s imagine we have this HTML: .. code:: html @@ -397,19 +235,9 @@ For example: font-size: 1.5rem !important; } -| Here we can see how we’ve used ``!important`` to force our - ``.heading-sub {}`` -| styles to reactively override our ``.content h2 {}`` selector. This - could have -| been circumvented by any number of things, including using better - Selector -| Intent, or avoiding nesting. +Here we can see how we’ve used ``!important`` to force our ``.heading-sub {}`` styles to reactively override our ``.content h2 {}`` selector. This could have been circumvented by any number of things, including using better Selector Intent, or avoiding nesting. -| In these situations, it is preferable that you investigate and - refactor any -| offending rulesets to try and bring specificity down across the board, - as -| opposed to introducing such specificity heavyweights. +In these situations, it is preferable that you investigate and refactor any offending rulesets to try and bring specificity down across the board, as opposed to introducing such specificity heavyweights. .. warning:: @@ -418,53 +246,23 @@ For example: Hacking Specificity ~~~~~~~~~~~~~~~~~~~ -| With all that said on the topic of specificity, and keeping it low, it - is -| inevitable that we will encounter problems. No matter how hard we try, - and how -| conscientious we are, there will always be times that we need to hack - and -| wrangle specificity. - -| When these situations do arise, it is important that we handle the - hacks as -| safely and elegantly as possible. - -| In the event that you need to increase the specificity of a class - selector, -| there are a number of options. We could nest the class inside - something else to -| bring its specificity up. For example, we could use - ``.header .site-nav {}`` to -| bring up the specificity of a simple ``.site-nav {}`` selector. - -| The problem with this, as we’ve discussed, is that it introduces - location -| dependency: these styles will only work when the ``.site-nav`` - component is in -| the ``.header`` component. - -| Instead, we can use a much safer hack that will not impact this - component’s -| portability: we can chain that class with itself: +With all that said on the topic of specificity, and keeping it low, it is inevitable that we will encounter problems. No matter how hard we try, and how conscientious we are, there will always be times that we need to hack and wrangle specificity. + +When these situations do arise, it is important that we handle the hacks as safely and elegantly as possible. + +In the event that you need to increase the specificity of a class selector, there are a number of options. We could nest the class inside something else to bring its specificity up. For example, we could use ``.header .site-nav {}`` to bring up the specificity of a simple ``.site-nav {}`` selector. + +The problem with this, as we’ve discussed, is that it introduces location dependency: these styles will only work when the ``.site-nav`` component is in the ``.header`` component. + +Instead, we can use a much safer hack that will not impact this component’s portability: we can chain that class with itself: .. code:: css .site-nav.site-nav { } -| This chaining doubles the specificity of the selector, but does not - introduce -| any dependency on location. +This chaining doubles the specificity of the selector, but does not introduce any dependency on location. -| In the event that we do, for whatever reason, have an ID in our markup - that we -| cannot replace with a class, select it via an attribute selector as - opposed to -| an ID selector. For example, let’s imagine we have embedded a - third-party -| widget on our page. We can style the widget via the markup that it - outputs, but -| we have no ability to edit that markup ourselves: +In the event that we do, for whatever reason, have an ID in our markup that we cannot replace with a class, select it via an attribute selector as opposed to an ID selector. For example, let’s imagine we have embedded a third-party widget on our page. We can style the widget via the markup that it outputs, but we have no ability to edit that markup ourselves: .. code:: html @@ -472,10 +270,7 @@ Hacking Specificity ... </div> -| Even though we know not to use IDs in CSS, what other option do we - have? We -| want to style this HTML but have no access to it, and all it has on it - is an ID. +Even though we know not to use IDs in CSS, what other option do we have? We want to style this HTML but have no access to it, and all it has on it is an ID. We do this: @@ -483,15 +278,9 @@ We do this: [id="third-party-widget"] { } -| Here we are selecting based on an attribute rather than an ID, and - attribute -| selectors have the same specificity as a class. This allows us to - style based -| on an ID, but without introducing its specificity. +Here we are selecting based on an attribute rather than an ID, and attribute selectors have the same specificity as a class. This allows us to style based on an ID, but without introducing its specificity. -| Do keep in mind that these are hacks, and should not be used unless - you have no -| better alternative. +Do keep in mind that these are hacks, and should not be used unless you have no better alternative. Further Reading ''''''''''''''' diff --git a/development/development/css_standards.rst b/development/development/css_standards.rst index a21348c0..a35ebac0 100644 --- a/development/development/css_standards.rst +++ b/development/development/css_standards.rst @@ -1,36 +1,23 @@ -| In working on large, long running projects with dozens of developers, - it is -| important that we all work in a unified way in order to, among other - things: +In working on large, long running projects with dozens of developers, it is important that we all work in a unified way in order to, among other things: - Keep code maintainable - Keep code transparent and readable - Keep code scalable -| There are a variety of techniques we must employ in order to satisfy - these -| goals. +There are a variety of techniques we must employ in order to satisfy these goals. The Importance of a Styleguide ------------------------------ -| A coding styleguide (note, not a visual styleguide) is a valuable tool - for teams -| who +A coding styleguide (note, not a visual styleguide) is a valuable tool for teams who - build and maintain products for a reasonable length of time; - have developers of differing abilities and specialisms; -- have a number of different developers working on a product at any - given time; +- have a number of different developers working on a product at any given time; - on-board new staff regularly; - have a number of codebases that developers dip in and out of. -| Whilst styleguides are typically more suited to production teams—large - codebases -| on long-lived and evolving projects, with multiple developers - contributing over -| prolonged periods of time—all developers should strive for a degree of -| standardization in their code. +Whilst styleguides are typically more suited to production teams—large codebases on long-lived and evolving projects, with multiple developers contributing over prolonged periods of time—all developers should strive for a degree of standardization in their code. A good styleguide, when well followed, will @@ -42,18 +29,11 @@ A good styleguide, when well followed, will Disclaimers ~~~~~~~~~~~ -| These Guidelines are a styleguide; they may not be the styleguide. - They contain -| methodologies, techniques, and tips that we firmly recommend to teams +These Guidelines are a styleguide; they may not be the styleguide. They contain methodologies, techniques, and tips that we firmly recommend to teams -| They are opinionated, but have been repeatedly tried, tested, - stressed, refined, -| broken, reworked, and revisited over a number of years on projects of - all sizes. +They are opinionated, but have been repeatedly tried, tested, stressed, refined, broken, reworked, and revisited over a number of years on projects of all sizes. -| They should be learned, understood, and implemented at all times on - this -| project, any deviation must be fully justified. +They should be learned, understood, and implemented at all times on this project, any deviation must be fully justified. Some General principles ----------------------- @@ -64,36 +44,23 @@ Some General principles clarity, not your personal preference of how to get clever within the spec.” - Idan Gazit -- Don’t try to prematurely optimize your code; keep it readable and - understandable. -- All code should look like a single person typed it, even when many - people are contributing to it. -- We use a strictly enforced agreed-upon style based on existing common - patterns. +- Don’t try to prematurely optimize your code; keep it readable and understandable. +- All code should look like a single person typed it, even when many people are contributing to it. +- We use a strictly enforced agreed-upon style based on existing common patterns. Meaningful Whitespace --------------------- -| Only one style should exist across the entire source of all your - code-base. -| Always be consistent in your use of whitespace. Use whitespace to - improve -| readability. +Only one style should exist across the entire source of all your code-base. Always be consistent in your use of whitespace. Use whitespace to improve readability. -- Never mix spaces and tabs for indentation. Stick to your choice - without fail. (**Preference: tabs**) -- Choose the number of preferred characters used per indentation level. - (**Preference: 4 spaces**) +- Never mix spaces and tabs for indentation. Stick to your choice without fail. (**Preference: tabs**) +- Choose the number of preferred characters used per indentation level. (**Preference: 4 spaces**) .. warning:: -configure your editor to “show invisibles” or to automatically remove -end-of-line whitespace. The use of an `EditorConfig`_ file is being used -to help maintain the basic whitespace conventions. +configure your editor to “show invisibles” or to automatically remove end-of-line whitespace. The use of an `EditorConfig`_ file is being used to help maintain the basic whitespace conventions. -| As well as indentation, we can provide a lot of information through - liberal and -| judicious use of whitespace between rulesets. We use: +As well as indentation, we can provide a lot of information through liberal and judicious use of whitespace between rulesets. We use: - One (1) empty line between closely related rulesets. - Two (2) empty lines between loosely related rulesets. @@ -113,9 +80,7 @@ For example: .foo--baz { } -| There should never be a scenario in which two rulesets do not have an - empty line -| between them. This would be incorrect: +There should never be a scenario in which two rulesets do not have an empty line between them. This would be incorrect: .. code:: scss @@ -126,57 +91,29 @@ For example: Multiple Files ~~~~~~~~~~~~~~ -| With the meteoric rise of preprocessors of late, more often is the - case that -| developers are splitting CSS across multiple files. +With the meteoric rise of preprocessors of late, more often is the case that developers are splitting CSS across multiple files. -| Even if not using a preprocessor, it is a good idea to split discrete - chunks of -| code into their own files, which are concatenated during a build step. +Even if not using a preprocessor, it is a good idea to split discrete chunks of code into their own files, which are concatenated during a build step. -| We follow the ITCSS principles for the organization of our code and as - such -| everything is broken up into partials. All partials are to be named to - reflect -| the contained component/module and lead by an underscore(\ ``_``) to - prevent self -| rendering. +We follow the ITCSS principles for the organization of our code and as such everything is broken up into partials. All partials are to be named to reflect the contained component/module and lead by an underscore(\ ``_``) to prevent self rendering. Commenting ---------- **CSS needs more comments.** -| The cognitive overhead of working with CSS is huge. With so much to be - aware of, -| and so many project-specific nuances to remember, the worst situation - most -| developers find themselves in is being - the-person-who-didn’t-write-this-code. -| Remembering your own classes, rules, objects, and helpers is - manageable to an -| extent, but anyone inheriting CSS barely stands a chance. - -| This is why well commented code is extremely important. Take time to - describe -| components, how they work, their limitations, and the way they are - constructed. -| Don’t leave others in the project guessing as to the purpose of - uncommon or -| non-obvious code. +The cognitive overhead of working with CSS is huge. With so much to be aware of, and so many project-specific nuances to remember, the worst situation most developers find themselves in is being the-person-who-didn’t-write-this-code. Remembering your own classes, rules, objects, and helpers is manageable to an extent, but anyone inheriting CSS barely stands a chance. + +This is why well commented code is extremely important. Take time to describe components, how they work, their limitations, and the way they are constructed. Don’t leave others in the project guessing as to the purpose of uncommon or non-obvious code. Comment style should be simple and consistent within the code base. - Place comments on a new line above their subject. - Keep line-length to a sensible maximum, e.g., 80 columns. -- Make liberal use of comments to break CSS code into discrete - sections. +- Make liberal use of comments to break CSS code into discrete sections. - Use “sentence case” comments and consistent text indentation. -| As CSS is something of a declarative language that doesn’t really - leave much of -| a paper-trail, it is often hard to discern—from looking at the CSS - alone— +As CSS is something of a declarative language that doesn’t really leave much of a paper-trail, it is often hard to discern—from looking at the CSS alone— - whether some CSS relies on other code elsewhere; - what effect changing some code will have elsewhere; @@ -185,98 +122,75 @@ Comment style should be simple and consistent within the code base. - what styles something might pass on (intentionally or otherwise); - where the author intended a piece of CSS to be used. -| This doesn’t even take into account some of CSS’ many quirks—such as - various -| sates of ``overflow`` triggering block formatting context, or certain - transform -| properties triggering hardware acceleration—that make it even more - baffling to -| developers inheriting projects. - -As a result of CSS not telling its own story very well, it is a - language that -| really does benefit from being heavily commented. - -| As a rule, you should comment anything that isn’t immediately obvious - from the -| code alone. That is to say, there is no need to tell someone that - ``color: red;`` -| will make something red, but if you’re using ``overflow: hidden;`` to - clear -| floats—as opposed to clipping an element’s overflow—this is probably - something -| worth documenting. +This doesn’t even take into account some of CSS’ many quirks—such as various sates of ``overflow`` triggering block formatting context, or certain transform properties triggering hardware acceleration—that make it even more baffling to developers inheriting projects. + +As a result of CSS not telling its own story very well, it is a language that really does benefit from being heavily commented. As a rule, you should comment anything that isn’t immediately obvious from the code alone. That is to say, there is no need to tell someone that ``color: red;`` will make something red, but if you’re using ``overflow: hidden;`` to clear floats—as opposed to clipping an element’s overflow—this is probably something worth documenting. .. warning:: -Tip: you can configure your editor to provide you with shortcuts to -output agreed-upon comment patterns. +Tip: you can configure your editor to provide you with shortcuts to output agreed-upon comment patterns. Comment Example: .. code:: scss - //------------------------------------------------------------------------------ - // #[LAYER]: PARTIAL NAME - //------------------------------------------------------------------------------ - // #description - // - // This is a description of the PARTIAL - // - //------------------------------------------------------------------------------ - - // - // #settings - - // Layout Variables - $variable: [value] - - // Theme Variables - $variable: [value] - - // - // #scss - - // - // 1. inline comment - // 2. inline comment - // 3. inline comment - // - - [selector] { - [property]: [value]; - [property]: [value]; // [1] - [property]: [value]; // [1] - [property]: [value]; // [2] - [property]: [value]; - [property]: [value]; // [3] - } - - // - // Section Block Comment - //------------------------------------------------------------------------------ - // - // 1. inline comment - // 2. inline comment - // 3. inline comment - // - [selector] { - [property]: [value]; - [property]: [value]; // [1] - [property]: [value]; // [1] - [property]: [value]; // [2] - [property]: [value]; - [property]: [value]; // [3] - } + //------------------------------------------------------------------------------ + // #[LAYER]: PARTIAL NAME + //------------------------------------------------------------------------------ + // #description + // + // This is a description of the PARTIAL + // + //------------------------------------------------------------------------------ + + // + // #settings + + // Layout Variables + $variable: [value] + + // Theme Variables + $variable: [value] + + // + // #scss + + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } + + // + // Section Block Comment + //------------------------------------------------------------------------------ + // + // 1. inline comment + // 2. inline comment + // 3. inline comment + // + [selector] { + [property]: [value]; + [property]: [value]; // [1] + [property]: [value]; // [1] + [property]: [value]; // [2] + [property]: [value]; + [property]: [value]; // [3] + } Low-level ~~~~~~~~~ -| Oftentimes we want to comment on specific declarations (i.e. lines) in - a -| ruleset. To do this we use a kind of reverse footnote. Here is a more - complex -| comment detailing the larger site headers mentioned above: +Oftentimes we want to comment on specific declarations (i.e. lines) in a ruleset. To do this we use a kind of reverse footnote. Here is a more complex comment detailing the larger site headers mentioned above: .. code:: scss @@ -321,9 +235,7 @@ Low-level will-change: box-shadow; } -| These types of comment allow us to keep all of our documentation in - one place -| whilst referring to the parts of the ruleset to which they belong. +These types of comment allow us to keep all of our documentation in one place whilst referring to the parts of the ruleset to which they belong. Titling ~~~~~~~ @@ -338,25 +250,13 @@ Begin every new major section of a CSS project with a title: .selector { } -| The title of the section is prefixed with a hash (``#``) symbol to - allow us to -| perform more targeted searches (e.g. ``grep``, etc.): instead of - searching for -| just ``SECTION-TITLE``—which may yield many results—a more scoped - search of -| ``#SECTION-TITLE`` should return only the section in question. +The title of the section is prefixed with a hash (``#``) symbol to allow us to perform more targeted searches (e.g. ``grep``, etc.): instead of searching for just ``SECTION-TITLE``—which may yield many results—a more scoped search of ``#SECTION-TITLE`` should return only the section in question. -| Leave a carriage return between this title and the next line of code - (be that a -| comment, some Sass, or some CSS). +Leave a carriage return between this title and the next line of code (be that a comment, some Sass, or some CSS). Preprocessor Comments ~~~~~~~~~~~~~~~~~~~~~ -| With most—if not all—preprocessors, we have the option to write - comments that -| will not get compiled out into our resulting CSS file. As a rule, use - these -| comments to speed up and prevent errors in the minification step. +With most—if not all—preprocessors, we have the option to write comments that will not get compiled out into our resulting CSS file. As a rule, use these comments to speed up and prevent errors in the minification step. .. _EditorConfig: http://editorconfig.org/ From 01abc4697718faae8f24f4283a18d019df227514 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Wed, 24 Jan 2018 21:37:11 -0500 Subject: [PATCH 19/98] make suggested changes --- development/development/css_guidelines.rst | 85 +++++++++++----------- development/development/css_naming.rst | 20 ++--- 2 files changed, 51 insertions(+), 54 deletions(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index e5000908..09677577 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -5,7 +5,7 @@ CSS is not a pretty language. While it is simple to learn and get started with, There are a variety of techniques we must employ in order to satisfy these goals, and CSS Guidelines is a document of recommendations and approaches that will help us to do so. -The first part of this will deal with syntax, formatting and CSS anatomy, the second part will deal with approach, mindframe and attitude toward writing and architecting CSS. +The first part of this will deal with syntax, formatting, and CSS anatomy. The second part will deal with approach, mindframe, and attitude toward writing/architecting CSS. Syntax and Formatting --------------------- @@ -14,14 +14,14 @@ One of the simplest forms of a styleguide is a set of rules regarding syntax and Further, code that looks clean feels clean. It is a much nicer environment to work in, and prompts other team members to maintain the standard of cleanliness that they found. Ugly code sets a bad precedent. -The chosen code format must ensure that code is: easy to read; easy to clearly comment; minimizes the chance of accidentally introducing errors; and results in useful diffs and blames. +The chosen code format must ensure that code is: easy to read, easy to clearly comment, minimizes the chance of accidentally introducing errors, and results in useful diffs and blames. At a very high-level, we want -- Tab (4 space width) indents; -- 80 character wide columns; -- multi-line CSS; -- a meaningful use of comments & whitespace. +- Tab (4 space width) indents +- 80 character wide columns +- multi-line CSS +- a meaningful use of comments & whitespace Anatomy of a Ruleset ~~~~~~~~~~~~~~~~~~~~ @@ -43,22 +43,22 @@ The following is a ``[ruleset]`` Formating ~~~~~~~~~ -- Use one discrete selector per line in multi-selector rulesets. -- The opening brace (``{``) should be on the same line as our last selector. -- Include a single space before the opening brace (``{``). -- Include properties and values on the same line. -- Include one declaration per line in a declaration block. -- Use one level of indentation for each declaration. -- Include a single space after the colon (``:``) of a declaration. -- Use lowercase hex values, e.g., #abc123. -- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""``. -- Always quote attribute values in selectors, e.g., ``input[type="checkbox"]``. -- Avoid specifying units for zero-values, e.g., ``margin: 0``. -- Always use leading zeros, e.g, ``font-size: 0.875rem`` -- Include a space after each comma(\ ``,``) in comma-separated property or function values. -- Include a semi-colon(\ ``;``) at the end of every declaration including the last in a declaration block. -- Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line. -- Separate each ruleset by a blank line. +- Use one discrete selector per line in multi-selector rulesets +- The opening brace (``{``) should be on the same line as our last selector +- Include a single space before the opening brace (``{``) +- Include properties and values on the same line +- Include one declaration per line in a declaration block +- Use one level of indentation for each declaration +- Include a single space after the colon (``:``) of a declaration +- Use lowercase hex values, e.g. #abc123 +- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""`` +- Always quote attribute values in selectors, e.g. ``input[type="checkbox"]`` +- Avoid specifying units for zero-values, e.g. ``margin: 0`` +- Always use leading zeros, e.g. ``font-size: 0.875rem`` +- Include a space after each comma(\ ``,``) in comma-separated property or function values +- Include a semi-colon(\ ``;``) at the end of every declaration including the last in a declaration block +- Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line +- Separate each ruleset by a blank line Example: @@ -97,12 +97,12 @@ As such, the following would be incorrect: Problems here include -- 2 spaces instead of tabs (4 space width). -- selectors on the same line. -- the opening brace (``{``) on its own line. -- the closing brace (``}``) does not sit on its own line. -- the last semi-colon (``;``) is missing. -- no spaces after colons (``:``). +- 2 spaces instead of tabs (4 space width) +- selectors on the same line +- the opening brace (``{``) on its own line +- the closing brace (``}``) does not sit on its own line +- the last semi-colon (``;``) is missing +- no spaces after colons (``:``) Multi-line CSS ~~~~~~~~~~~~~~ @@ -130,8 +130,8 @@ Exceptions to this rule should be fairly apparent, such as similar rulesets that These types of ruleset benefit from being single-lined because -- they still conform to the one-reason-to-change-per-line rule; -- they share enough similarities that they don’t need to be read as thoroughly as other rulesets—there is more benefit in being able to scan their selectors, which are of more interest to us in these cases. +- they still conform to the one-reason-to-change-per-line rule +- they share enough similarities that they don’t need to be read as thoroughly as other rulesets - there is more benefit in being able to scan their selectors, which are of more interest to us in these cases Declaration order ~~~~~~~~~~~~~~~~~ @@ -180,22 +180,22 @@ Example: content: "-"; } -Proper Use of units +Proper use of units ~~~~~~~~~~~~~~~~~~~ -CSS allows for the use of several different unit types. As such it can get confusing when using more than one type of unit through out the project. For that reason its beneficial to stick to a stick set of rules for what unit types are to be used for certain selectors. +CSS allows for the use of several different unit types. As such it can get confusing when using more than one type of unit throughout, it's for that reason its beneficial to stick to a strict set of rules for what unit types are to be used for certain selectors. Furthermore there are certain reasons to use or avoid using specific units in certain places. EM ^^ -The ‘em’ unit. This is a very problematic unit which reeks havoc on countless projects due to the way its calculated. As such this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for ``letter-spaceing`` & ``word-spacing``. It is also used for icon sizing but that is an edge case. +The ‘em’ unit. This is a very problematic unit which wreaks havoc on countless projects due to the way its calculated. As such this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for ``letter-spacing`` & ``word-spacing``. It is also used for icon sizing but that is an edge case. Line-heights ^^^^^^^^^^^^ -All line-heights are to be specified as ``unitless`` in order to prevent in proper inheritance. By nature when using units with line-heights the children inherit by default. This can lead to unwanted effects and bloated code. A ``sass`` function called ``unitless`` is provided which will convert px values for convenience, but for clarity the math is simply +All line-heights are to be specified as ``unitless`` in order to prevent improper inheritance. By nature when using units with line-heights the children inherit by default. This can lead to unwanted effects and bloated code. A ``sass`` function called ``unitless`` is provided which will convert px values for convenience, but for clarity the math is simply .. code:: scss @@ -209,17 +209,17 @@ All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. Margins & Paddings ^^^^^^^^^^^^^^^^^^ -All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` All px values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. +All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. PX ^^ -All ``px`` will be whole numbers. Browsers do not render ``px`` in fractional values despite what you browser may say it is. Only calculated values will display as fractional ``px``. For clarification a calculated value would be units like ``rem``, ``em``, ``%``, & even ``unitless`` as is the case with line-heights. +All ``px`` will be whole numbers. Browsers do not render ``px`` in fractional values despite what your browser may say it is. Only calculated values will display as fractional ``px``. For clarification a calculated value would be units like ``rem``, ``em``, ``%``, & even ``unitless`` as is the case with line-heights. Dimensions ^^^^^^^^^^ -All dimensional values ``width``, ``min-width``, ``height``, & ``min-height`` should be specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, but they are still on the fringe of browser acceptance, as such fallbacks in ``px`` or ``%`` are required. These values will remain as px if specified. This is done as ``height`` is more effectively and appropriately controlled via the ``line-height`` property, and ``width`` is better specified using the objects box-model via ``padding`` unless its fluid in which ``100%`` can be specified or u can also use ``left: 0; right: 0;`` +All dimensional values ``width``, ``min-width``, ``height``, & ``min-height`` should be specified in ``px`` or ``%``. A case can be made for ``vw`` & ``vh``, but they are still on the fringe of browser acceptance, as such fallbacks in ``px`` or ``%`` are required. These values will remain as px if specified. This is done as ``height`` is more effectively and appropriately controlled via the ``line-height`` property, and ``width`` is better specified using the objects box-model via ``padding`` unless its fluid in which ``100%`` can be specified or you can also use ``left: 0; right: 0;`` Indenting Sass ^^^^^^^^^^^^^^ @@ -236,14 +236,14 @@ Sass provides nesting functionality. That is to say, by writing this: } } -…we will be left with this compiled CSS: +… we will be left with this compiled CSS: .. code:: css .foo { color: red; } .foo .bar { color: blue; } -When indenting Sass, we stick to the same two indentation, and we also leave a blank line before and after the nested ruleset. +When indenting Sass, we stick to the same four space tab indentation, and we also leave a blank line before and after the nested ruleset. **N.B.** Nesting in Sass should be avoided in most cases. See the Specificity section for more data @@ -257,7 +257,7 @@ Our project makes use of several tools to lint and to keep us to the standards. .. note:: -This is used to provide detailed linting for our standards via the ``.stlyelintrc`` file in the root of the project. +This is used to provide detailed linting for our standards via the ``.stylelintrc`` file in the root of the project. 2. `postcss-sorting`_ ^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ This is used to provide automatic sorting to our declaration order via the ``.po .. note:: -This is used to ensure the proper units are consistently used throughout the project during the build process via the ``gulp`` as well as on save in your editor. +This is used to ensure the proper units are consistently used throughout the project during the build process via ``gulp`` as well as on save in your editor. 4. `stylefmt`_ ^^^^^^^^^^^^^^ @@ -282,11 +282,12 @@ This is used to help automatically re-format your code to the standards on the f .. note:: -As a **NOTE** our editor of choice is `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information +As a **NOTE** our editors of choice are `PhpStorm`_ & `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information .. _stylelint.io: http://www.stylelint.io .. _postcss-sorting: https://github.com/hudochenkov/postcss-sorting .. _postcss-pxtorem: https://github.com/cuth/postcss-pxtorem .. _stylefmt: https://github.com/morishitter/stylefmt +.. _PhpStorm: https://www.jetbrains.com/phpstorm/ .. _ATOM: http://www.atom.io .. _Editor Setup: /editor-setup diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst index b69471c7..a21198f5 100644 --- a/development/development/css_naming.rst +++ b/development/development/css_naming.rst @@ -5,17 +5,17 @@ Naming conventions in CSS are hugely useful in making your code more strict, mor A good naming convention will tell you and your team -- what type of thing a class does; -- where a class can be used; -- what (else) a class might be related to. +- what type of thing a class does +- where a class can be used +- what (else) a class might be related to The naming convention we follow are as follows -- Hyphen (``-``) delimited strings. +- Hyphen (``-``) delimited strings - Layer namespacing - A variation on BEM-like naming for action modifiers -It’s worth noting that not all the naming convention are normally useful in the CSS-side of development; they really come into their own when viewed in HTML. +It’s worth noting that not all the naming conventions are normally useful in the CSS side of development; they really come into their own when viewed in HTML. Hyphen Delimited ~~~~~~~~~~~~~~~~ @@ -143,11 +143,7 @@ Further Reading JavaScript Hooks ~~~~~~~~~~~~~~~~ -As a rule, it is unwise to bind your CSS and your JS onto the same class in your HTML. This is because doing so means you can’t have (or remove) one without (removing) the other. It is much cleaner, much more transparent, and much more maintainable to bind your JS onto specific classes. - -I have known occasions before when trying to refactor some CSS has unwittingly removed JS functionality because the two were tied to each other—it was impossible to have one without the other. - -Typically, these are classes that are prepended with ``js-``, for +As a rule, it is unwise to bind your CSS and your JS onto the same class in your HTML. This is because doing so means you can’t have (or remove) one without (removing) the other. It is much cleaner, much more transparent, and much more maintainable to bind your JS onto specific classes. Typically, this is why you sometimes se classes that are prepended with ``js-``, for example: @@ -155,12 +151,12 @@ example: <input type="submit" class="btn js-btn" value="Follow" /> -This means that we can have an element elsewhere which can carry with style of ``.btn {}``, but without the behavior of ``.js-btn``. +This means that we can have an element elsewhere which can carry the style of ``.btn {}``, but without the behavior of ``.js-btn``. ``data-*`` Attributes ^^^^^^^^^^^^^^^^^^^^^ -A common practice is to use ``data-*`` attributes as JS hooks, but this is incorrect. ``data-*`` attributes, as per the spec, are used to store custom data private to the page or application’\* (emphasis Harry Roberts). ``data-*`` attributes are designed to store data, not be bound to. +A cleaner and preferred practice is to use ``data-*`` attributes as JS hooks.``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. .. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 .. _SUITcss: https://suitcss.github.io/ From 82ff59d78bf11e3cb38988dd7da895306dd70380 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 27 Jan 2018 10:05:23 -0500 Subject: [PATCH 20/98] re-write css_selectors --- development/development/css_selectors.rst | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst index 9e593c6a..160a0da3 100644 --- a/development/development/css_selectors.rst +++ b/development/development/css_selectors.rst @@ -1,18 +1,18 @@ CSS Selectors ------------- -Perhaps somewhat surprisingly, one of the most fundamental, critical aspects of writing maintainable and scalable CSS is selectors. Their specificity, their portability, and their reusability all have a direct impact on the mileage we will get out of our CSS, and the headaches it might bring us. +Perhaps somewhat surprisingly, one of the most fundamental, critical aspects of writing maintainable and scalable CSS is selectors. Their specificity, their portability, and their reusability all have a direct impact on the mileage you will get out of the CSS, and the headaches it might bring you. Selector Intent ~~~~~~~~~~~~~~~ -It is important when writing CSS that we scope our selectors correctly, and that we’re selecting the right things for the right reasons. Selector Intent is the process of deciding and defining what you want to style and how you will go about selecting it. For example, if you are wanting to style your website’s main navigation menu, a selector like this would be incredibly unwise: +It is important when writing CSS that you scope the selectors correctly, and that you're selecting the right things for the right reasons. Selector Intent is the process of deciding and defining what you want to style and how you will go about selecting it. For example, if you are wanting to style your website’s main navigation menu, a selector like this would be incredibly unwise: .. code:: css header ul { } -This selector’s intent is to style any ``ul`` inside any ``header`` element, whereas our intent was to style the site’s main navigation. This is poor Selector Intent: you can have any number of ``header`` elements on a page, and they in turn can house any number of ``uls``, so a selector like this runs the risk of applying very specific styling to a very wide number of elements. This will result in having to write more CSS to undo the greedy nature of such a selector. +This selector’s intent is to style any ``ul`` inside any ``header`` element, whereas your intent was to style the site’s main navigation. This is poor Selector Intent: you can have any number of ``header`` elements on a page, and they in turn can house any number of ``uls``, so a selector like this runs the risk of applying very specific styling to a very wide number of elements. This will result in having to write more CSS to undo the greedy nature of such a selector. A better approach would be a selector like: @@ -20,31 +20,31 @@ A better approach would be a selector like: .site-nav { } -An unambiguous, explicit selector with good Selector Intent. We are explicitly selecting the right thing for exactly the right reason. +An unambiguous, explicit selector with good Selector Intent. Explicitly selecting the right thing for exactly the right reason. -Poor Selector Intent is one of the biggest reasons for headaches on CSS projects. Writing rules that are far too greedy—and that apply very specific treatments via very far reaching selectors—causes unexpected side effects and leads to very tangled stylesheets, with selectors overstepping their intentions and impacting and interfering with otherwise unrelated rulesets. +Poor Selector Intent is one of the biggest reasons for headaches on CSS projects. Writing rules that are far too greedy, and apply very specific treatments via very far reaching selectors. This causes unexpected side effects and leads to very tangled stylesheets, with selectors overstepping their intentions and impacting and interfering with otherwise unrelated rulesets. -CSS cannot be encapsulated, it is inherently leaky, but we can mitigate some of these effects by not writing such globally-operating selectors: **your selectors should be as explicit and well reasoned as your reason for wanting to select something.** +CSS cannot be encapsulated, it is inherently leaky, but you can mitigate some of these effects by not writing such globally operating selectors: **your selectors should be as explicit and well reasoned as your reason for wanting to select something.** Reusability ~~~~~~~~~~~ -With a move toward a more component-based approach to constructing UIs, the idea of reusability is paramount. We want the option to be able to move, recycle, duplicate, and syndicate components across our projects. +With a move toward a more component based approach to constructing UIs, the idea of reusability is paramount. You want the option to be able to move, recycle, duplicate, and syndicate components across our projects. -To this end, we make heavy use of classes. IDs, as well as being hugely over-specific, cannot be used more than once on any given page, whereas classes can be reused an infinite amount of times. Everything you choose, from the type of selector to its name, should lend itself toward being reused. +To this end, make heavy use of classes. IDs, as well as being hugely over specific, cannot be used more than once on any given page. Classes can be reused an infinite amount of times. Everything you choose, from the type of selector to its name, should lend itself toward being reused. Location Independence ~~~~~~~~~~~~~~~~~~~~~ -Given the ever-changing nature of most UI projects, and the move to more component-based architectures, it is in our interests not to style things based on where they are, but on what they are. That is to say, our components’ styling should not be reliant upon where we place them—they should remain entirely location independent. +Given the ever changing nature of most UI projects, and the move to more component based architectures, it is in your best interest not to style things based on where they are, but on what they are. That is to say, your components’ styling should not be reliant upon where its placed. They should remain entirely location independent. -Let’s take an example of a call-to-action button that we have chosen to style via the following selector: +Let’s take an example of a call-to-action button that has been styled via the following selector: .. code:: css .promo a { } -Not only does this have poor Selector Intent—it will greedily style any and every link inside of a ``.promo`` to look like a button—it is also pretty wasteful as a result of being so locationally dependent: we can’t reuse that button with its correct styling outside of ``.promo`` because it is explicitly tied to that location. A far better selector would have been: +Not only does this have poor Selector Intent, it will greedily style any and every link inside of a ``.promo`` to look like a button. It is also pretty wasteful as a result of being so locationally dependent: you can’t reuse that button with its correct styling outside of ``.promo`` because it is explicitly tied to that location. A far better selector would have been: .. code:: css @@ -55,17 +55,17 @@ This single class can be reused anywhere outside of ``.promo`` and will always c Portability ~~~~~~~~~~~ -Reducing, or, ideally, removing, location dependence means that we can move components around our markup more freely, but how about improving our ability to move classes around components? On a much lower level, there are changes we can make to our selectors that make the selectors themselves—as opposed to the components they create—more portable. Take the following example: +Reducing or removing, location dependence means that you can move components around our markup more freely, but how about improving the ability to move classes around components? On a much lower level, there are changes you can make to your selectors that make the selectors themselves, as opposed to the components they create more portable. Take the following example: .. code:: css input.btn { } -This is a *qualified* selector; the leading ``input`` ties this ruleset to only being able to work on ``input`` elements. By omitting this qualification, we allow ourselves to reuse the ``.btn`` class on any element we choose, like an ``a``, for example, or a ``button``. +This is a *qualified* selector; the leading ``input`` ties this ruleset to only being able to work on ``input`` elements. By omitting this qualification, you allow the reuse of the ``.btn`` class on any element you choose, like an ``a``, for example, or a ``button``. -Qualified selectors do not lend themselves well to being reused, and every selector we write should be authored with reuse in mind. +Qualified selectors do not lend themselves well to being reused, and every selector you write should be authored with reuse in mind. -Of course, there are times when you may want to legitimately qualify a selector—you might need to apply some very specific styling to a particular element when it carries a certain class, for example: +Of course, there are times when you may want to legitimately qualify a selector, you might need to apply some very specific styling to a particular element when it carries a certain class, for example: .. code:: css @@ -85,7 +85,7 @@ Of course, there are times when you may want to legitimately qualify a selector border: 1px solid; } -This is one example where a qualified selector might be justifiable, but I would still recommend an approach more like: +This is one example where a qualified selector might be justifiable, but the recommend approach would be: .. code:: css @@ -105,7 +105,7 @@ This is one example where a qualified selector might be justifiable, but I would border: 1px solid; } -This means that we can apply ``.error-box`` to any element, and not just a ``div``—it is more reusable than a qualified selector. +This means that you can apply ``.error-box`` to any element, and not just a ``div`` it is more reusable than a qualified selector. Quasi-Qualified Selectors ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,13 +116,13 @@ One thing that qualified selectors can be useful for is signaling where a class ul.nav { } -Here we can see that the ``.nav`` class is meant to be used on a ``ul`` element, and not on a ``nav``. By using *quasi-qualified selectors* we can still provide that information without actually qualifying the selector: +Here you can see that the ``.nav`` class is meant to be used on a ``ul`` element, and not on a ``nav``. By using *quasi-qualified selectors* you can still provide that information without actually qualifying the selector: .. code:: css /*ul*/.nav { } -By commenting out the leading element, we can still leave it to be read, but avoid qualifying and increasing the specificity of the selector. +By commenting out the leading element, you can still leave it to be read, but avoid qualifying and increasing the specificity of the selector. Naming ~~~~~~ @@ -132,21 +132,21 @@ As Phil Karlton once said ‘There are only two hard things in Computer Science: cache invalidation and naming things.’ -I won’t comment on the former claim here, but the latter has plagued me for years. My advice with regard to naming things in CSS is to pick a name that is sensible, but somewhat ambiguous: aim for high reusability. For example, instead of a class like ``.site-nav``, choose something like ``.primary-nav``; rather than ``.footer-links``, favor a class like ``.sub-links``. +Without commenting on the former claim here, but the latter has plagued people for years. Our advice with regard to naming things in CSS is to pick a name that is sensible, but somewhat ambiguous: aim for high reusability. For example, instead of a class like ``.site-nav``, choose something like ``.primary-nav``; rather than ``.footer-links``, favor a class like ``.sub-links``. -The differences in these names is that the first of each two examples is tied to a very specific use case: they can only be used as the site’s navigation or the footer’s links respectively. By using slightly more ambiguous names, we can increase our ability to reuse these components in different circumstances. +The differences in these names is that the first of each two examples is tied to a very specific use case: they can only be used as the site’s navigation or the footer’s links respectively. By using slightly more ambiguous names, you can increase the ability to reuse these components in different circumstances. To quote Nicolas Gallagher: - Tying your class name semantics tightly to the nature of the content + 'Tying your class name semantics tightly to the nature of the content has already reduced the ability of your architecture to scale or be - easily put to use by other developers. + easily put to use by other developers.' -That is to say, we should use sensible names—classes like ``.border`` or ``.red`` are never advisable—but we should avoid using classes which describe the exact nature of the content and/or its use cases. **Using a class name to describe content is redundant because content describes itself.** +That is to say, you should use sensible names or classes. For example ``.border`` or ``.red`` are never advisable, avoid using classes which describe the exact nature of the content and/or its use cases. **Using a class name to describe content is redundant because content describes itself.** -The debate surrounding semantics has raged for years, but it is important that we adopt a more pragmatic, sensible approach to naming things in order to work more efficiently and effectively. Instead of focussing on ‘semantics’,look more closely at sensibility and longevity—choose names based on ease of maintenance, not for their perceived meaning. +The debate surrounding semantics has raged for years, but it is important that you adopt a more pragmatic, sensible approach to naming things in order to work more efficiently and effectively. Instead of focussing on ‘semantics’, look more closely at sensibility and longevity, choose names based on ease of maintenance, not for their perceived meaning. -Name things for people; they’re the only things that actually read your classes (everything else merely matches them). Once again, it is better to strive for reusable, recyclable classes rather than writing for specific use cases. Let’s take an example: +Name things for people; they’re the only ones that actually read your classes (everything else merely matches them). Once again, it is better to strive for reusable, recyclable classes rather than writing for specific use cases. Let’s take an example: .. code:: css @@ -161,7 +161,7 @@ Name things for people; they’re the only things that actually read your classe .header span { color: blue; } /** - * Too specific; limits our ability to reuse. + * Too specific; limits the ability to reuse. */ .header-color { color: blue; } @@ -175,7 +175,7 @@ It is important to strike a balance between names that do not literally describe Selector Performance ~~~~~~~~~~~~~~~~~~~~ -A topic which is—with the quality of today’s browsers—more interesting than it is important, is selector performance. That is to say, how quickly a browser can match the selectors your write in CSS up with the nodes it finds in the DOM. +A topic which is with the quality of today’s browsers, more interesting than it is important, is selector performance. That is to say, how quickly a browser can match the selectors you write in CSS up with the nodes it finds in the DOM. Generally speaking, the longer a selector is (i.e. the more component parts) the slower it is, for example: @@ -197,20 +197,20 @@ This is because browsers read CSS selectors right-to-left. A browser will read t - now check that that all lives anywhere inside any elements with a class of ``.home``; - finally, check that ``.home`` exists on a ``body`` element. -The second, in contrast, is simply a case of the browser reading find all the elements with a class of ``.primary-nav``. +The second, in contrast, is simply a case of the browser reading, find all the elements with a class of ``.primary-nav``. -To further compound the problem, we are using descendant selectors (e.g. ``.foo .bar {}``). The upshot of this is that a browser is required to start with the rightmost part of the selector (i.e. ``.bar``) and keep looking up the DOM indefinitely until it finds the next part (i.e. ``.foo``). This could mean stepping up the DOM dozens of times until a match is found. +To further compound the problem, the example uses descendant selectors (e.g. ``.foo .bar {}``). The upshot of this is that a browser is required to start with the rightmost part of the selector (i.e. ``.bar``) and keep looking up the DOM indefinitely until it finds the next part (i.e. ``.foo``). This could mean stepping up the DOM dozens of times until a match is found. This is just one reason why **nesting with preprocessors is often a false economy**; as well as making selectors unnecessarily more specific, and creating location dependency, it also creates more work for the browser. -By using a child selector (e.g. ``.foo > .bar {}``) we can make the process much more efficient, because this only requires the browser to look one level higher in the DOM, and it will stop regardless of whether or not it found a match. +By using a child selector (e.g. ``.foo > .bar {}``) you can make the process much more efficient, because this only requires the browser to look one level higher in the DOM, and it will stop regardless of whether or not it found a match. The Key Selector ^^^^^^^^^^^^^^^^ Because browsers read selectors right-to-left, the rightmost selector is often critical in defining a selector’s performance: this is called the key selector. -The following selector might appear to be highly performant at first glance. It uses an ID which is nice and fast, and there can only ever be one on a page, so surely this will be a nice and speedy lookup—just find that one ID and then style everything inside of it: +The following selector might appear to be highly performant at first glance. It uses an ID which is nice and fast, and there can only ever be one on a page, so surely this will be a nice and speedy lookup, just find that one ID and then style everything inside of it: .. code:: css @@ -218,7 +218,7 @@ The following selector might appear to be highly performant at first glance. It The problem with this selector is that the key selector (``*``) is very, very far reaching. What this selector actually does is find every single node in the DOM (even ``<title>``, ``<link>``, and ``<head>`` elements; everything) and then looks to see if it lives anywhere at any level within #foo. This is a very, very expensive selector, and should most likely be avoided or rewritten. -Thankfully, by writing selectors with good Selector Intent, we are probably avoiding inefficient selectors by default; we are very unlikely to have greedy key selectors if we’re targeting the right things for the right reason. +Thankfully, by writing selectors with good Selector Intent, you are probably avoiding inefficient selectors by default; you are very unlikely to have greedy key selectors if you’re targeting the right things for the right reason. That said, however, CSS selector performance should be fairly low on your list of things to optimize; browsers are fast, and are only ever getting faster, and it is only on notable edge cases that inefficient selectors would be likely to pose a problem. @@ -235,7 +235,7 @@ Your selectors are fundamental to writing good CSS. To very briefly sum up the a - **Do not qualify selectors unnecessarily**, as this will impact the number of different elements you can apply styles to. - **Keep selectors as short as possible**, in order to keep specificity down and performance up. -Focussing on these points will keep your selectors a lot more sane and easy to work with on changing and long-running projects. +Focussing on these points will keep your selectors a lot more sane and easy to work with on changing and long running projects. Further Reading ''''''''''''''' From bd1cae5a41454b6958895d7ac200ba1aa995bad0 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 31 Mar 2018 09:25:47 -0400 Subject: [PATCH 21/98] bullet formating tweaks --- development/development/css_selectors.rst | 10 ++-- development/development/css_specificity.rst | 18 +++---- development/development/css_standards.rst | 54 ++++++++++----------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst index 160a0da3..e33d88ae 100644 --- a/development/development/css_selectors.rst +++ b/development/development/css_selectors.rst @@ -191,11 +191,11 @@ Generally speaking, the longer a selector is (i.e. the more component parts) the This is because browsers read CSS selectors right-to-left. A browser will read the first selector as -- find all ``ul`` elements in the DOM; -- now check if they live anywhere inside an element with a class of ``.header``; -- next check that ``.header`` class exists on a ``div`` element; -- now check that that all lives anywhere inside any elements with a class of ``.home``; -- finally, check that ``.home`` exists on a ``body`` element. +- find all ``ul`` elements in the DOM +- now check if they live anywhere inside an element with a class of ``.header`` +- next check that ``.header`` class exists on a ``div`` element +- now check that that all lives anywhere inside any elements with a class of ``.home`` +- finally, check that ``.home`` exists on a ``body`` element The second, in contrast, is simply a case of the browser reading, find all the elements with a class of ``.primary-nav``. diff --git a/development/development/css_specificity.rst b/development/development/css_specificity.rst index 31493684..4e57dfb2 100644 --- a/development/development/css_specificity.rst +++ b/development/development/css_specificity.rst @@ -39,11 +39,11 @@ Now we have a selector that is even more specific still! And if we ever want to Specificity can, among other things, -- limit your ability to extend and manipulate a codebase; -- interrupt and undo CSS’ cascading, inheriting nature; -- cause avoidable verbosity in your project; -- prevent things from working as expected when moved into different environments; -- lead to serious developer frustration. +- limit your ability to extend and manipulate a codebase +- interrupt and undo CSS’ cascading, inheriting nature +- cause avoidable verbosity in your project +- prevent things from working as expected when moved into different environments +- lead to serious developer frustration All of these issues are greatly magnified when working on a larger project with a number of developers contributing code. @@ -58,10 +58,10 @@ Doing so will instantly help us tame and manage the project, meaning that no ove Simple changes to the way we work include, but are not limited to, -- not using IDs in your CSS; -- not nesting selectors; -- not qualifying classes; -- not chaining selectors. +- not using IDs in your CSS +- not nesting selectors +- not qualifying classes +- not chaining selectors **Specificity can be wrangled and understood, but it is safer just to avoid it entirely.** diff --git a/development/development/css_standards.rst b/development/development/css_standards.rst index a35ebac0..db2f92d3 100644 --- a/development/development/css_standards.rst +++ b/development/development/css_standards.rst @@ -11,20 +11,20 @@ The Importance of a Styleguide A coding styleguide (note, not a visual styleguide) is a valuable tool for teams who -- build and maintain products for a reasonable length of time; -- have developers of differing abilities and specialisms; -- have a number of different developers working on a product at any given time; -- on-board new staff regularly; -- have a number of codebases that developers dip in and out of. +- build and maintain products for a reasonable length of time +- have developers of differing abilities and specialisms +- have a number of different developers working on a product at any given time +- on-board new staff regularly +- have a number of codebases that developers dip in and out of Whilst styleguides are typically more suited to production teams—large codebases on long-lived and evolving projects, with multiple developers contributing over prolonged periods of time—all developers should strive for a degree of standardization in their code. A good styleguide, when well followed, will -- set the standard for code quality across a codebase; -- promote consistency across codebases; -- give developers a feeling of familiarity across codebases; -- increase productivity. +- set the standard for code quality across a codebase +- promote consistency across codebases +- give developers a feeling of familiarity across codebases +- increase productivity Disclaimers ~~~~~~~~~~~ @@ -44,17 +44,17 @@ Some General principles clarity, not your personal preference of how to get clever within the spec.” - Idan Gazit -- Don’t try to prematurely optimize your code; keep it readable and understandable. -- All code should look like a single person typed it, even when many people are contributing to it. -- We use a strictly enforced agreed-upon style based on existing common patterns. +- Don’t try to prematurely optimize your code; keep it readable and understandable +- All code should look like a single person typed it, even when many people are contributing to it +- We use a strictly enforced agreed-upon style based on existing common patterns Meaningful Whitespace --------------------- Only one style should exist across the entire source of all your code-base. Always be consistent in your use of whitespace. Use whitespace to improve readability. -- Never mix spaces and tabs for indentation. Stick to your choice without fail. (**Preference: tabs**) -- Choose the number of preferred characters used per indentation level. (**Preference: 4 spaces**) +- Never mix spaces and tabs for indentation. Stick to your choice without fail (**Preference: tabs**) +- Choose the number of preferred characters used per indentation level (**Preference: 4 spaces**) .. warning:: @@ -62,8 +62,8 @@ configure your editor to “show invisibles” or to automatically remove end-of As well as indentation, we can provide a lot of information through liberal and judicious use of whitespace between rulesets. We use: -- One (1) empty line between closely related rulesets. -- Two (2) empty lines between loosely related rulesets. +- One (1) empty line between closely related rulesets +- Two (2) empty lines between loosely related rulesets For example: @@ -108,19 +108,19 @@ This is why well commented code is extremely important. Take time to describe co Comment style should be simple and consistent within the code base. -- Place comments on a new line above their subject. -- Keep line-length to a sensible maximum, e.g., 80 columns. -- Make liberal use of comments to break CSS code into discrete sections. -- Use “sentence case” comments and consistent text indentation. +- Place comments on a new line above their subject +- Keep line-length to a sensible maximum, e.g., 80 columns +- Make liberal use of comments to break CSS code into discrete sections +- Use “sentence case” comments and consistent text indentation -As CSS is something of a declarative language that doesn’t really leave much of a paper-trail, it is often hard to discern—from looking at the CSS alone— +As CSS is something of a declarative language that doesn’t really leave much of a paper-trail, it is often hard to discern—from looking at the CSS alone -- whether some CSS relies on other code elsewhere; -- what effect changing some code will have elsewhere; -- where else some CSS might be used; -- what styles something might inherit (intentionally or otherwise); -- what styles something might pass on (intentionally or otherwise); -- where the author intended a piece of CSS to be used. +- whether some CSS relies on other code elsewhere +- what effect changing some code will have elsewhere +- where else some CSS might be used +- what styles something might inherit (intentionally or otherwise) +- what styles something might pass on (intentionally or otherwise) +- where the author intended a piece of CSS to be used This doesn’t even take into account some of CSS’ many quirks—such as various sates of ``overflow`` triggering block formatting context, or certain transform properties triggering hardware acceleration—that make it even more baffling to developers inheriting projects. From 1717f488b8f1f0256b178e7d0cffa34e51429895 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 31 Mar 2018 09:25:59 -0400 Subject: [PATCH 22/98] fix typo --- development/development/css_naming.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst index a21198f5..097dcc0f 100644 --- a/development/development/css_naming.rst +++ b/development/development/css_naming.rst @@ -57,7 +57,7 @@ To take an analogy (note, not an example): .dropdown-item { } .dropdown--active { } -Elements are delimited with two (hyphens (``-``), and Modifiers are delimited by two (2) hyphens (``--``). +Elements are delimited with one (1) hyphen (``-``), and Modifiers are delimited by two (2) hyphens (``--``). Here we can see that ``.dropdown {}`` is the Block; it is the sole root of a discrete entity. ``.dropdown-item {}`` is an Element; it is a smaller part of the ``.dropdown {}`` Block. Finally, ``.dropdown--active {}`` is a Modifier; it is a specific variant of the ``.dropdown {}`` Block. From e3d3f8fc9d11ae16331610299a2a460b2d6c2f72 Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 31 Mar 2018 09:26:16 -0400 Subject: [PATCH 23/98] remove unnessecary comma --- development/development/css_guidelines.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index 09677577..e1638caa 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -51,7 +51,7 @@ Formating - Use one level of indentation for each declaration - Include a single space after the colon (``:``) of a declaration - Use lowercase hex values, e.g. #abc123 -- Use quotes consistently. **Preference double quotes**, e.g., ``content: ""`` +- Use quotes consistently. **Preference double quotes**, e.g. ``content: ""`` - Always quote attribute values in selectors, e.g. ``input[type="checkbox"]`` - Avoid specifying units for zero-values, e.g. ``margin: 0`` - Always use leading zeros, e.g. ``font-size: 0.875rem`` From 3ee105d6769af6038fb3c0268a64d7eb14a8fa2e Mon Sep 17 00:00:00 2001 From: Michael Miday <midaym@gmail.com> Date: Sat, 31 Mar 2018 09:26:35 -0400 Subject: [PATCH 24/98] remove unessecary backslashes --- development/development/css_guidelines.rst | 4 ++-- development/development/css_standards.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index e1638caa..2b5faf5c 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -55,8 +55,8 @@ Formating - Always quote attribute values in selectors, e.g. ``input[type="checkbox"]`` - Avoid specifying units for zero-values, e.g. ``margin: 0`` - Always use leading zeros, e.g. ``font-size: 0.875rem`` -- Include a space after each comma(\ ``,``) in comma-separated property or function values -- Include a semi-colon(\ ``;``) at the end of every declaration including the last in a declaration block +- Include a space after each comma (``,``) in comma-separated property or function values +- Include a semi-colon (``;``) at the end of every declaration including the last in a declaration block - Place the closing brace (``}``) of a ruleset in the same column as the first character of the ruleset, on its own line - Separate each ruleset by a blank line diff --git a/development/development/css_standards.rst b/development/development/css_standards.rst index db2f92d3..f08e2e2e 100644 --- a/development/development/css_standards.rst +++ b/development/development/css_standards.rst @@ -95,7 +95,7 @@ With the meteoric rise of preprocessors of late, more often is the case that dev Even if not using a preprocessor, it is a good idea to split discrete chunks of code into their own files, which are concatenated during a build step. -We follow the ITCSS principles for the organization of our code and as such everything is broken up into partials. All partials are to be named to reflect the contained component/module and lead by an underscore(\ ``_``) to prevent self rendering. +We follow the ITCSS principles for the organization of our code and as such everything is broken up into partials. All partials are to be named to reflect the contained component/module and lead by an underscore (``_``) to prevent self rendering. Commenting ---------- From 79ed86aa8c93529074038aa4af53993e55fcd362 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Thu, 13 Sep 2018 16:48:04 +0200 Subject: [PATCH 25/98] Fix generation of CSS styleguide documentation --- development/development/css_guidelines.rst | 20 +++++------------ development/development/css_naming.rst | 4 ++-- development/development/css_selectors.rst | 2 +- development/development/css_specificity.rst | 24 ++++++--------------- development/development/css_standards.rst | 8 ++----- development/development/index.rst | 11 ++++++++++ development/index.rst | 2 ++ development/language/guidelines.rst | 2 +- development/language/validation.rst | 5 +++-- 9 files changed, 34 insertions(+), 44 deletions(-) create mode 100644 development/development/index.rst diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index 2b5faf5c..0a38432d 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -255,34 +255,24 @@ Our project makes use of several tools to lint and to keep us to the standards. 1. `stylelint.io`_ ^^^^^^^^^^^^^^^^^^ -.. note:: - -This is used to provide detailed linting for our standards via the ``.stylelintrc`` file in the root of the project. +.. note:: This is used to provide detailed linting for our standards via the ``.stylelintrc`` file in the root of the project. 2. `postcss-sorting`_ ^^^^^^^^^^^^^^^^^^^^^ -.. note:: - -This is used to provide automatic sorting to our declaration order via the ``.postcss-sorting.json`` file in the root of the project. +.. note:: This is used to provide automatic sorting to our declaration order via the ``.postcss-sorting.json`` file in the root of the project. 3. `postcss-pxtorem`_ ^^^^^^^^^^^^^^^^^^^^^ -.. note:: - -This is used to ensure the proper units are consistently used throughout the project during the build process via ``gulp`` as well as on save in your editor. +.. note:: This is used to ensure the proper units are consistently used throughout the project during the build process via ``gulp`` as well as on save in your editor. 4. `stylefmt`_ ^^^^^^^^^^^^^^ -.. note:: - -This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. - -.. note:: +.. note:: This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. -As a **NOTE** our editors of choice are `PhpStorm`_ & `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information +.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information .. _stylelint.io: http://www.stylelint.io .. _postcss-sorting: https://github.com/hudochenkov/postcss-sorting diff --git a/development/development/css_naming.rst b/development/development/css_naming.rst index 097dcc0f..9c55027f 100644 --- a/development/development/css_naming.rst +++ b/development/development/css_naming.rst @@ -136,7 +136,7 @@ In no particular order, here are the individual namespaces and a brief descripti Even from this short list alone, we can see just how much more information we can communicate to developers simply by placing a character or two at the front of our existing classes. Further Reading -''''''''''''''' +^^^^^^^^^^^^^^^ - `UI Selector Namspacing`_ @@ -156,7 +156,7 @@ This means that we can have an element elsewhere which can carry the style of `` ``data-*`` Attributes ^^^^^^^^^^^^^^^^^^^^^ -A cleaner and preferred practice is to use ``data-*`` attributes as JS hooks.``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. +A cleaner and preferred practice is to use ``data-*`` attributes as JS hooks. ``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. .. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 .. _SUITcss: https://suitcss.github.io/ diff --git a/development/development/css_selectors.rst b/development/development/css_selectors.rst index e33d88ae..7a63efe4 100644 --- a/development/development/css_selectors.rst +++ b/development/development/css_selectors.rst @@ -238,7 +238,7 @@ Your selectors are fundamental to writing good CSS. To very briefly sum up the a Focussing on these points will keep your selectors a lot more sane and easy to work with on changing and long running projects. Further Reading -''''''''''''''' +^^^^^^^^^^^^^^^ - `Shoot to kill; CSS selector intent`_ - `‘Scope’ in CSS`_ diff --git a/development/development/css_specificity.rst b/development/development/css_specificity.rst index 4e57dfb2..c681e24e 100644 --- a/development/development/css_specificity.rst +++ b/development/development/css_specificity.rst @@ -70,21 +70,15 @@ IDs in CSS If we want to keep specificity low, which we do, we have one really quick-win, simple, easy-to-follow rule that we can employ to help us: -.. warning:: - -**NEVER USE IDs in CSS** +.. warning:: **NEVER USE IDs in CSS** Not only are IDs inherently non-reusable, they are also vastly more specific than any other selector, and therefore become specificity anomalies. Where the rest of your selectors are relatively low specificity, your ID-based selectors are, comparatively, much, much higher. In fact, to highlight the severity of this difference, see how one thousand chained classes cannot override the specificity of a single ID: `jsfiddle.net/0yb7rque`_. -.. warning:: - -(Please note that in Firefox you may see the text rendering in blue: this is a `known bug`_, and an ID will be overridden by 256 chained classes.) - -.. note:: +.. warning:: Please note that in Firefox you may see the text rendering in blue: this is a `known bug`_, and an ID will be overridden by 256 chained classes. -**N.B.** It is still perfectly okay to use IDs in HTML and JavaScript; it is only in CSS that they prove troublesome. +.. note:: **N.B.** It is still perfectly okay to use IDs in HTML and JavaScript; it is only in CSS that they prove troublesome. It is often suggested that developers who choose not to use IDs in CSS merely don’t understand how specificity works. This is as incorrect as it is offensive: no matter how experienced a developer you are, this behavior cannot be circumvented; no amount of knowledge will make an ID less specific. @@ -164,9 +158,7 @@ To style an element with a class of ``.widget-title``, we have a selector that i Not only is this entirely avoidable—we caused this problem ourselves—we have a selector that is literally double the specificity it needs to be. We used 200% of the specificity actually required. And not only that, but this also leads to needless verbosity in our code—more to send over the wire. -.. warning:: - -As a rule, **if a selector will work without it being nested then do not nest it.** +.. warning:: As a rule, **if a selector will work without it being nested then do not nest it.** Scope ~~~~~ @@ -178,7 +170,7 @@ This goes some way to providing our CSS with scope and encapsulation, but does s Now we have better scoped CSS with minimal specificity—the best of both worlds. Further Reading -''''''''''''''' +^^^^^^^^^^^^^^^ - `‘Scope’ in CSS`_ @@ -239,9 +231,7 @@ Here we can see how we’ve used ``!important`` to force our ``.heading-sub {}`` In these situations, it is preferable that you investigate and refactor any offending rulesets to try and bring specificity down across the board, as opposed to introducing such specificity heavyweights. -.. warning:: - -**Only use** ``!important`` **proactively, not reactively.** +.. warning:: **Only use** ``!important`` **proactively, not reactively.** Hacking Specificity ~~~~~~~~~~~~~~~~~~~ @@ -283,7 +273,7 @@ Here we are selecting based on an attribute rather than an ID, and attribute sel Do keep in mind that these are hacks, and should not be used unless you have no better alternative. Further Reading -''''''''''''''' +^^^^^^^^^^^^^^^ - `Hacks for dealing with specificity`_ diff --git a/development/development/css_standards.rst b/development/development/css_standards.rst index f08e2e2e..582c71c8 100644 --- a/development/development/css_standards.rst +++ b/development/development/css_standards.rst @@ -56,9 +56,7 @@ Only one style should exist across the entire source of all your code-base. Alwa - Never mix spaces and tabs for indentation. Stick to your choice without fail (**Preference: tabs**) - Choose the number of preferred characters used per indentation level (**Preference: 4 spaces**) -.. warning:: - -configure your editor to “show invisibles” or to automatically remove end-of-line whitespace. The use of an `EditorConfig`_ file is being used to help maintain the basic whitespace conventions. +.. warning:: configure your editor to “show invisibles” or to automatically remove end-of-line whitespace. The use of an `EditorConfig`_ file is being used to help maintain the basic whitespace conventions. As well as indentation, we can provide a lot of information through liberal and judicious use of whitespace between rulesets. We use: @@ -126,9 +124,7 @@ This doesn’t even take into account some of CSS’ many quirks—such as vario As a result of CSS not telling its own story very well, it is a language that really does benefit from being heavily commented. As a rule, you should comment anything that isn’t immediately obvious from the code alone. That is to say, there is no need to tell someone that ``color: red;`` will make something red, but if you’re using ``overflow: hidden;`` to clear floats—as opposed to clipping an element’s overflow—this is probably something worth documenting. -.. warning:: - -Tip: you can configure your editor to provide you with shortcuts to output agreed-upon comment patterns. +.. warning:: Tip: you can configure your editor to provide you with shortcuts to output agreed-upon comment patterns. Comment Example: diff --git a/development/development/index.rst b/development/development/index.rst new file mode 100644 index 00000000..d22a22c4 --- /dev/null +++ b/development/development/index.rst @@ -0,0 +1,11 @@ +CSS Coding Styleguide +====================== + +.. toctree:: + :maxdepth: 2 + + css_standards + css_guidelines + css_naming + css_selectors + css_specificity diff --git a/development/index.rst b/development/index.rst index f21f533d..95cff913 100644 --- a/development/index.rst +++ b/development/index.rst @@ -6,8 +6,10 @@ Contents: .. toctree:: :maxdepth: 2 + db/dbal development/git development/coding_guidelines + development/index cli/index extensions/index files/index diff --git a/development/language/guidelines.rst b/development/language/guidelines.rst index 9235577d..33dabf0f 100644 --- a/development/language/guidelines.rst +++ b/development/language/guidelines.rst @@ -14,7 +14,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of 2) Submissions have to be complete. Partial translations are not allowed and will be automatically denied. E-mails, text files and theme-images must also be fully translated. -3) Language packs can contain five additional files (one mandatory and four optionals) that are not present in the British English language pack: ``LICENSE`` (mandatory), ``README.md`` (optional), ``AUTHORS.md`` (optional), ``VERSION.md`` (optional) and ``CHANGELOG.md`` (optional). You are free to write whatever you want in the ``README.md`` file, you can list all the authors and contributors of your language pack in the ``AUTHORS.md`` file, you can put the version of your language pack in the ``VERSION.md`` file and you can list the entire version history in the ``CHANGELOG.md`` file. The ``LICENSE`` file is automatically added during the upload process so you do not have to manually add the file. Its purpose is to inform the user what license is used. Language packs inherit phpBB's license of GNU General Public License 2.0_ and no additional or alternative licenses are allowed. All of these additional files must be placed in the ``language/{iso}/`` directory, next to the ``iso.txt`` file. Any other additional file(s) will be detected and your submission will be denied. +3) Language packs can contain five additional files (one mandatory and four optionals) that are not present in the British English language pack: ``LICENSE`` (mandatory), ``README.md`` (optional), ``AUTHORS.md`` (optional), ``VERSION.md`` (optional) and ``CHANGELOG.md`` (optional). You are free to write whatever you want in the ``README.md`` file, you can list all the authors and contributors of your language pack in the ``AUTHORS.md`` file, you can put the version of your language pack in the ``VERSION.md`` file and you can list the entire version history in the ``CHANGELOG.md`` file. The ``LICENSE`` file is automatically added during the upload process so you do not have to manually add the file. Its purpose is to inform the user what license is used. Language packs inherit phpBB's license of GNU General Public License 2.0 and no additional or alternative licenses are allowed. All of these additional files must be placed in the ``language/{iso}/`` directory, next to the ``iso.txt`` file. Any other additional file(s) will be detected and your submission will be denied. 4) Submissions must have the following files and structure: diff --git a/development/language/validation.rst b/development/language/validation.rst index dc0585e4..8b281803 100644 --- a/development/language/validation.rst +++ b/development/language/validation.rst @@ -113,8 +113,8 @@ contains the default html body: </body> </html> -language/{iso}/help/*.php -------------------------- +language/{iso}/help/\*.php +-------------------------- * The file must must only contain 1 array named `$lang`. No other variables are allowed. * The array must only contain arrays with the following structure: @@ -237,4 +237,5 @@ License * All translations must be released under `GNU General Public License 2.0 <http://www.opensource.org/licenses/gpl-2.0.php>`_ + .. _Customisation Database: https://www.phpbb.com/go/customise/language-packs/3.2 From 72d008928b331df8c2deaef35ca66bb5c40d2207 Mon Sep 17 00:00:00 2001 From: Yuriy Rusko <github@rusko.org> Date: Thu, 13 Sep 2018 17:06:08 +0200 Subject: [PATCH 26/98] Language improvements --- development/development/css_guidelines.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/development/development/css_guidelines.rst b/development/development/css_guidelines.rst index 0a38432d..34dfc8e7 100644 --- a/development/development/css_guidelines.rst +++ b/development/development/css_guidelines.rst @@ -183,19 +183,19 @@ Example: Proper use of units ~~~~~~~~~~~~~~~~~~~ -CSS allows for the use of several different unit types. As such it can get confusing when using more than one type of unit throughout, it's for that reason its beneficial to stick to a strict set of rules for what unit types are to be used for certain selectors. +Because CSS allows for the use of several different unit types, it can get confusing when using more than one type of unit throughout. For that reason it's beneficial to stick to a strict set of rules for what unit types are to be used for certain selectors. Furthermore there are certain reasons to use or avoid using specific units in certain places. EM ^^ -The ‘em’ unit. This is a very problematic unit which wreaks havoc on countless projects due to the way its calculated. As such this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for ``letter-spacing`` & ``word-spacing``. It is also used for icon sizing but that is an edge case. +The ‘em’ unit. This is a very problematic unit which wreaks havoc on countless projects due to the way it's calculated. As such, this unit type must be avoid except for very very minimal use cases. We prevent the use of ``em`` except for ``letter-spacing`` & ``word-spacing``. It is also used for icon sizing, but that is an edge case. Line-heights ^^^^^^^^^^^^ -All line-heights are to be specified as ``unitless`` in order to prevent improper inheritance. By nature when using units with line-heights the children inherit by default. This can lead to unwanted effects and bloated code. A ``sass`` function called ``unitless`` is provided which will convert px values for convenience, but for clarity the math is simply +All line-heights are to be specified as ``unitless`` in order to prevent improper inheritance. By nature when using units with line-heights, the children inherit by default. This can lead to unwanted effects and bloated code. A ``sass`` function called ``unitless`` is provided which will convert px values for convenience, but for clarity the math is simply .. code:: scss @@ -204,12 +204,12 @@ All line-heights are to be specified as ``unitless`` in order to prevent imprope Font-size ^^^^^^^^^ -All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. All px values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. +All ``font-size`` should be specified either in ``px`` or ``%`` in small cases. All px values will be converted to ``rem`` during the build process as ``rem`` provides for control in responsive situations. Margins & Paddings ^^^^^^^^^^^^^^^^^^ -All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` values will be converted to ``rem`` during the build process as ``rem`` provide for control in responsive situations. +All ``margin`` & ``padding`` should be specified in ``px`` values or ``%``. All ``px`` values will be converted to ``rem`` during the build process as ``rem`` provides for control in responsive situations. PX ^^ @@ -250,7 +250,7 @@ When indenting Sass, we stick to the same four space tab indentation, and we als Enforcing standardization ~~~~~~~~~~~~~~~~~~~~~~~~~ -Our project makes use of several tools to lint and to keep us to the standards. +Our project makes use of several tools to lint and keep code up to standards. 1. `stylelint.io`_ ^^^^^^^^^^^^^^^^^^ @@ -265,14 +265,14 @@ Our project makes use of several tools to lint and to keep us to the standards. 3. `postcss-pxtorem`_ ^^^^^^^^^^^^^^^^^^^^^ -.. note:: This is used to ensure the proper units are consistently used throughout the project during the build process via ``gulp`` as well as on save in your editor. +.. note:: This is used to ensure that proper units are consistently used throughout the project during the build process via ``gulp`` as well as on save in your editor. 4. `stylefmt`_ ^^^^^^^^^^^^^^ -.. note:: This is used to help automatically re-format your code to the standards on the fly during the build process via ``gulp`` as well as on save in your editor. +.. note:: This is used to help automatically re-format your code on-the-fly to meet standards during the build process via ``gulp`` as well as on save in your editor. -.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provides usefull plugins to make use of these tools. Checkout the `Editor Setup`_ section of the docs for more information +.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information .. _stylelint.io: http://www.stylelint.io .. _postcss-sorting: https://github.com/hudochenkov/postcss-sorting From 82a62714639c99d07413bef586776ca27064b73a Mon Sep 17 00:00:00 2001 From: Michael Miday <hanakin@users.noreply.github.com> Date: Thu, 14 Mar 2019 12:54:01 -1000 Subject: [PATCH 27/98] Change name to CSS Coding Guidlines --- development/development/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/development/index.rst b/development/development/index.rst index d22a22c4..99c02f58 100644 --- a/development/development/index.rst +++ b/development/development/index.rst @@ -1,4 +1,4 @@ -CSS Coding Styleguide +CSS Coding Guidelines ====================== .. toctree:: From a5a2a0978c742b63c58eb8671f930f290235f217 Mon Sep 17 00:00:00 2001 From: hanakin <midaym@gmail.com> Date: Thu, 14 Mar 2019 19:05:33 -1000 Subject: [PATCH 28/98] squash all the commits, finish php, fix errors --- development/development/coding_guidelines.rst | 31 - .../development/{ => css}/css_guidelines.rst | 0 .../development/{ => css}/css_naming.rst | 9 +- .../development/{ => css}/css_selectors.rst | 0 .../development/{ => css}/css_specificity.rst | 0 .../development/{ => css}/css_standards.rst | 0 development/development/css/index.rst | 22 + development/development/index.rst | 22 +- development/development/js/index.rst | 15 + .../php/character_set_and_encodings.rst | 57 ++ development/development/php/defaults.rst | 202 ++++ development/development/php/index.rst | 11 + .../development/php/layout_guidelines.rst | 903 ++++++++++++++++++ development/development/php/templating.rst | 491 ++++++++++ development/index.rst | 7 +- development/start/getting_started.rst | 178 ++++ development/start/install.rst | 290 ++++++ 17 files changed, 2192 insertions(+), 46 deletions(-) delete mode 100644 development/development/coding_guidelines.rst rename development/development/{ => css}/css_guidelines.rst (100%) rename development/development/{ => css}/css_naming.rst (90%) rename development/development/{ => css}/css_selectors.rst (100%) rename development/development/{ => css}/css_specificity.rst (100%) rename development/development/{ => css}/css_standards.rst (100%) create mode 100644 development/development/css/index.rst create mode 100644 development/development/js/index.rst create mode 100644 development/development/php/character_set_and_encodings.rst create mode 100644 development/development/php/defaults.rst create mode 100644 development/development/php/index.rst create mode 100644 development/development/php/layout_guidelines.rst create mode 100644 development/development/php/templating.rst create mode 100644 development/start/getting_started.rst create mode 100644 development/start/install.rst diff --git a/development/development/coding_guidelines.rst b/development/development/coding_guidelines.rst deleted file mode 100644 index b8b5e2a2..00000000 --- a/development/development/coding_guidelines.rst +++ /dev/null @@ -1,31 +0,0 @@ -Coding Guidelines -================= - -phpBB's coding guidelines are maintained in its -`source code repository <https://github.com/phpbb/phpbb>`_. You can find the -latest versions on area51: - -* Rules for `Olympus (3.0.x) code <http://area51.phpbb.com/docs/30x/coding-guidelines.html>`_ -* Rules for `Ascraeus (3.1.x) code <http://area51.phpbb.com/docs/31x/coding-guidelines.html>`_ -* Rules for `Rhea (3.2.x) code <http://area51.phpbb.com/docs/32x/coding-guidelines.html>`_ - -These documents are automatically updated when changes are made to them. - -JavaScript Linting ------------------- - -We use JSHint and JSCS for checking the quality of the JavaScript—JSHint for -linting, and JSCS for ensuring consistent code. There is a .jshintrc and a -.jscs file in the root of the project, and your editor probably has a plugin -available which will show you when you violate these standards. - -CSS & SCSS Linting ------------------- - -We use `stylelint <https://stylelint.io/>`_ for checking the quality, linting, -and ensuring consistent CSS code standards. There is a .stylelintrc -file in the root of the project, and your editor probably has a plugin available -which will show you when you violate these standards. - -We employ a set of standards loosely based on the following widely used -`CSS Guidelines <http://cssguidelin.es/>`_ diff --git a/development/development/css_guidelines.rst b/development/development/css/css_guidelines.rst similarity index 100% rename from development/development/css_guidelines.rst rename to development/development/css/css_guidelines.rst diff --git a/development/development/css_naming.rst b/development/development/css/css_naming.rst similarity index 90% rename from development/development/css_naming.rst rename to development/development/css/css_naming.rst index 9c55027f..87723419 100644 --- a/development/development/css_naming.rst +++ b/development/development/css/css_naming.rst @@ -131,7 +131,6 @@ In no particular order, here are the individual namespaces and a brief descripti - ``s-``: Signify that a class creates a new styling context or Scope. Similar to a Theme, but not necessarily cosmetic, these should be used sparingly—they can be open to abuse and lead to poor CSS if not used wisely. - ``is-``, ``has-``: Signify that the piece of UI in question is currently styled a certain way because of a state or condition. This stateful namespace is gorgeous, and comes from `SMACSS`_. It tells us that the DOM currently has a temporary, optional, or short-lived style applied to it due to a certain state being invoked. - ``_``: Signify that this class is the worst of the worst—a hack! Sometimes, although incredibly rarely, we need to add a class in our markup in order to force something to work. If we do this, we need to let others know that this class is less than ideal, and hopefully temporary (i.e. do not bind onto this). -- ``js``-: Signify that this piece of the DOM has some behavior acting upon it, and that JavaScript binds onto it to provide that behavior. If you’re not a developer working with JavaScript, leave these well alone. Even from this short list alone, we can see just how much more information we can communicate to developers simply by placing a character or two at the front of our existing classes. @@ -143,20 +142,20 @@ Further Reading JavaScript Hooks ~~~~~~~~~~~~~~~~ -As a rule, it is unwise to bind your CSS and your JS onto the same class in your HTML. This is because doing so means you can’t have (or remove) one without (removing) the other. It is much cleaner, much more transparent, and much more maintainable to bind your JS onto specific classes. Typically, this is why you sometimes se classes that are prepended with ``js-``, for +As a rule, it is unwise to bind your CSS and your JS onto the same class in your HTML. This is because doing so means you can’t have (or remove) one without (removing) the other. It is much cleaner, much more transparent, and much more maintainable to bind your JS onto data attributes. example: .. code:: html - <input type="submit" class="btn js-btn" value="Follow" /> + <input type="submit" class="btn" data-execute="addSomething" value="Follow" /> -This means that we can have an element elsewhere which can carry the style of ``.btn {}``, but without the behavior of ``.js-btn``. +This means that we can have an element elsewhere which can carry the style of ``.btn {}``, but without the behavior of ``data-execute="addSomething"``. ``data-*`` Attributes ^^^^^^^^^^^^^^^^^^^^^ -A cleaner and preferred practice is to use ``data-*`` attributes as JS hooks. ``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. +It is our preferred practice to use ``data-*`` attributes as JS hooks. ``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. .. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 .. _SUITcss: https://suitcss.github.io/ diff --git a/development/development/css_selectors.rst b/development/development/css/css_selectors.rst similarity index 100% rename from development/development/css_selectors.rst rename to development/development/css/css_selectors.rst diff --git a/development/development/css_specificity.rst b/development/development/css/css_specificity.rst similarity index 100% rename from development/development/css_specificity.rst rename to development/development/css/css_specificity.rst diff --git a/development/development/css_standards.rst b/development/development/css/css_standards.rst similarity index 100% rename from development/development/css_standards.rst rename to development/development/css/css_standards.rst diff --git a/development/development/css/index.rst b/development/development/css/index.rst new file mode 100644 index 00000000..e441502d --- /dev/null +++ b/development/development/css/index.rst @@ -0,0 +1,22 @@ +CSS Coding Guidelines +====================== + +We use `stylelint <https://stylelint.io/>`_ for checking the quality, linting, and ensuring consistent CSS code standards. There is a ``.stylelintrc`` file and a ``postcss-sorting.json`` file in the root of the project, and your editor probably has a plugin available which will show you when you violate these standards. + +We employ a set of standards loosely based on the following widely used +`CSS Guidelines <http://cssguidelin.es/>`_ + +.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information + +.. _PhpStorm: https://www.jetbrains.com/phpstorm/ +.. _ATOM: http://www.atom.io +.. _Editor Setup: /editor-setup + +.. toctree:: + :maxdepth: 2 + + css_standards + css_guidelines + css_naming + css_selectors + css_specificity diff --git a/development/development/index.rst b/development/development/index.rst index 99c02f58..7a43a197 100644 --- a/development/development/index.rst +++ b/development/development/index.rst @@ -1,11 +1,19 @@ -CSS Coding Guidelines -====================== +Coding Guidelines +================= + +phpBB's coding guidelines are maintained in its +`source code repository <https://github.com/phpbb/phpbb>`_. You can find the +latest versions on area51: + +* Rules for `Olympus (3.0.x) code <http://area51.phpbb.com/docs/30x/coding-guidelines.html>`_ +* Rules for `Ascraeus (3.1.x) code <http://area51.phpbb.com/docs/31x/coding-guidelines.html>`_ +* Rules for `Rhea (3.2.x) code <http://area51.phpbb.com/docs/32x/coding-guidelines.html>`_ + +These documents are automatically updated when changes are made to them. .. toctree:: :maxdepth: 2 - css_standards - css_guidelines - css_naming - css_selectors - css_specificity + php + js + css diff --git a/development/development/js/index.rst b/development/development/js/index.rst new file mode 100644 index 00000000..b9bfdeeb --- /dev/null +++ b/development/development/js/index.rst @@ -0,0 +1,15 @@ +JavaScript Guidelines +===================== + +We use `XO.js <https://github.com/xojs/xo>`_ for checking the quality, linting, and ensuring consistent JS code standards. Its installed via npm as a module and is configured via the ``package.json`` file in the root. Your editor probably has a plugin available which will show you when you violate these standards. ``XO.js`` is an `ESLint <https://eslint.org/>`_ wrapper. Its essentially a custom `config <https://github.com/xojs/eslint-config-xo/blob/master/index.js>`_ for ESlint, but simplifies the use as we do not have to manitain/update the standards. This means we do not need to manage an ``eslintrc`` file. + +.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information + +.. _PhpStorm: https://www.jetbrains.com/phpstorm/ +.. _ATOM: http://www.atom.io +.. _Editor Setup: /editor-setup + +.. toctree:: + :maxdepth: 2 + + test diff --git a/development/development/php/character_set_and_encodings.rst b/development/development/php/character_set_and_encodings.rst new file mode 100644 index 00000000..0cdad7b4 --- /dev/null +++ b/development/development/php/character_set_and_encodings.rst @@ -0,0 +1,57 @@ +5. Character Sets and Encodings +=============================== + +What are Unicode, UCS and UTF-8? +-------------------------------- + +The `Universal Character Set (UCS) <http://en.wikipedia.org/wiki/Universal_Character_Set>`_ described in ISO/IEC 10646 consists of a large amount of characters. Each of them has a unique name and a code point which is an integer number. `Unicode <http://en.wikipedia.org/wiki/Unicode>`_ - which is an industry standard - complements the Universal Character Set with further information about the characters' properties and alternative character encodings. More information on Unicode can be found on the `Unicode Consortium's website <http://www.unicode.org/>`_. One of the Unicode encodings is the `8-bit Unicode Transformation Format (UTF-8) <http://en.wikipedia.org/wiki/UTF-8>`_. It encodes characters with up to four bytes aiming for maximum compatibility with the `American Standard Code for Information Interchange <http://en.wikipedia.org/wiki/ASCII>`_ which is a 7-bit encoding of a relatively small subset of the UCS. + +phpBB's use of Unicode +++++++++++++++++++++++ + +Unfortunately PHP does not facilitate the use of Unicode prior to version 6. Most functions simply treat strings as sequences of bytes assuming that each character takes up exactly one byte. This behaviour still allows for storing UTF-8 encoded text in PHP strings but many operations on strings have unexpected results. To circumvent this problem we have created some alternative functions to PHP's native string operations which use code points instead of bytes. These functions can be found in ``/includes/utf/utf_tools.php``. A lot of native PHP functions still work with UTF-8 as long as you stick to certain restrictions. For example ``explode`` still works as long as the first and the last character of the delimiter string are ASCII characters. + +phpBB only uses the ASCII and the UTF-8 character encodings. Still all Strings are UTF-8 encoded because ASCII is a subset of UTF-8. The only exceptions to this rule are code sections which deal with external systems which use other encodings and character sets. Such external data should be converted to UTF-8 using the ``utf8_recode()`` function supplied with phpBB. It supports a variety of other character sets and encodings, a full list can be found below. + +With ``$request->variable()`` you can either allow all UCS characters in user input or restrict user input to ASCII characters. This feature is controlled by the method's third parameter called ``$multibyte``. You should allow multibyte characters in posts, PMs, topic titles, forum names, etc. but it's not necessary for internal uses like a ``$mode`` variable which should only hold a predefined list of ASCII strings anyway. + +.. code: php + // an input string containing a multibyte character + $_REQUEST['multibyte_string'] = 'Käse'; + + // print request variable as a UTF-8 string allowing multibyte characters + echo $request->variable('multibyte_string', '', true); + // print request variable as ASCII string + echo $request->variable('multibyte_string', ''); + +This code snippet will generate the following output: + +.. code: text + Käse + K??se + +Case Folding +++++++++++++ + +Case insensitive comparison of strings is no longer possible with ``strtolower`` or ``strtoupper`` as some characters have multiple lower case or multiple upper case forms depending on their position in a word. The ``utf8_strtolower`` and the ``utf8_strtoupper`` functions suffer from the same problem so they can only be used to display upper/lower case versions of a string but they cannot be used for case insensitive comparisons either. So instead you should use case folding which gives you a case insensitive version of the string which can be used for case insensitive comparisons. An NFC normalized string can be case folded using ``utf8_case_fold_nfc()``. + +**Bad - The strings might be the same even if strtolower differs:** + +.. code: php + if (strtolower($string1) == strtolower($string2)) + { + echo '$string1 and $string2 are equal or differ in case'; + } + +**Good - Case folding is really case insensitive:** + + + if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2)) + { + echo '$string1 and $string2 are equal or differ in case'; + } + +Confusables Detection ++++++++++++++++++++++ + +phpBB offers a special method ``utf8_clean_string`` which can be used to make sure string identifiers are unique. This method uses Normalization Form Compatibility Composition (NFKC) instead of NFC and replaces similarly looking characters with a particular representative of the equivalence class. This method is currently used for usernames and group names to avoid confusion with similarly looking names. diff --git a/development/development/php/defaults.rst b/development/development/php/defaults.rst new file mode 100644 index 00000000..af56026b --- /dev/null +++ b/development/development/php/defaults.rst @@ -0,0 +1,202 @@ +1. Defaults +=========== + +1.i. Editor Settings +-------------------- + +Tabs vs Spaces ++++++++++++++++ + +In order to make this as simple as possible, we will be using tabs, not spaces. We enforce 4 (four) spaces for one tab - therefore you need to set your tab width within your editor to 4 spaces. Make sure that when you **save** the file, it's saving tabs and not spaces. This way, we can each have the code be displayed the way we like it, without breaking the layout of the actual files. + +Tabs in front of lines are no problem, but having them within the text can be a problem if you do not set it to the amount of spaces every one of us uses. Here is a short example of how it should look like: + +.. code:: php + {TAB}$mode{TAB}{TAB}= $request->variable('mode', ''); + {TAB}$search_id{TAB}= $request->variable('search_id', ''); + +If entered with tabs (replace the {TAB}) both equal signs need to be on the same column. + +Linefeeds +++++++++++ + +Ensure that your editor is saving files in the UNIX (LF) line ending format. This means that lines are terminated with a newline, not with Windows Line endings (CR/LF combo) as they are on Win32 or Classic Mac (CR) Line endings. Any decent editor should be able to do this, but it might not always be the default setting. Know your editor. If you want advice for an editor for your Operating System, just ask one of the developers. Some of them do their editing on Win32. + +1.ii. File Layout +----------------- + +Standard header for new files: +This template of the header must be included at the start of all phpBB files: + +.. code:: php + /** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +Please see the `1.iii. File Locations`_ section for the correct package name. + +PHP closing tags +++++++++++++++++ + +A file containg only PHP code should not end with the optional PHP closing tag ``?>`` to avoid issues with whitespace following it. + +Newline at end of file +++++++++++++++++++++++ + +All files should end in a newline so the last line does not appear as modified in diffs, when a line is appended to the file. + +Files containing inline code +++++++++++++++++++++++++++++ + +For those files you have to put an empty comment directly after the header to prevent the documentor assigning the header to the first code element found. + +.. code:: php + /** + * {HEADER} + */ + + /** + */ + {CODE} + +Files containing only functions ++++++++++++++++++++++++++++++++ + +Do not forget to comment the functions (especially the first function following the header). Each function should have at least a comment of what this function does. For more complex functions it is recommended to document the parameters too. + +Files containing only classes ++++++++++++++++++++++++++++++ + +Do not forget to comment the class. Classes need a separate @package definition, it is the same as the header package name. Apart from this special case the above statement for files containing only functions needs to be applied to classes and it's methods too. + +Code following the header but only functions/classes file ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +If this case is true, the best method to avoid documentation confusions is adding an ignore command, for example: + +.. code:: php + /** + * {HEADER} + */ + + /** + * @ignore + */ + Small code snipped, mostly one or two defines or an if statement + + /** + * {DOCUMENTATION} + */ + class ... + +1.iii. File Locations +--------------------- + +Functions used by more than one page should be placed in functions.php, functions specific to one page should be placed on that page (at the bottom) or within the relevant sections functions file. Some files in /includes are holding functions responsible for special sections, for example uploading files, displaying "things", user related functions and so forth. + +The following packages are defined, and related new features/functions should be placed within the mentioned files/locations, as well as specifying the correct package name. The package names are bold within this list: + +**phpBB3** +Core files and all files not assigned to a separate package +**acm** +``/phpbb/cache`` +Cache System +**acp** +``/adm``, ``/includes/acp``, ``/includes/functions_admin.php`` +Administration Control Panel +**dbal** +``/phpbb/db``, ``/includes/db`` +Database Abstraction Layer. +``/phpbb/db/driver/`` +Database Abstraction Layer classes +``/phpbb/db/migration/`` +Migrations are used for updating the database from one release to another +**diff** +``/includes/diff`` +Diff Engine +**images** +``/images`` +All global images not connected to styles +**install** +``/install`` +Installation System +**language** +``/language`` +All language files +**login** +``/phpbb/auth`` +Login Authentication Plugins +**VC** +``/includes/captcha`` +CAPTCHA +**mcp** +``mcp.php``, ``/includes/mcp``, ``report.php`` +Moderator Control Panel +**ucp** +``ucp.php``, ``/includes/ucp`` +User Control Panel +**utf** +``/includes/utf`` +UTF8-related functions/classes +**search** +``/phpbb/search``, ``search.php`` +Search System +**styles** +``/styles`` +phpBB Styles/Templates/Themes + +1.iv. Special Constants +----------------------- + +There are some special constants application developers are able to utilize to bend some of phpBB's internal functionality to suit their needs. + +.. code:: php + PHPBB_MSG_HANDLER (overwrite message handler) + PHPBB_DB_NEW_LINK (overwrite new_link parameter for sql_connect) + PHPBB_ROOT_PATH (overwrite $phpbb_root_path) + PHPBB_ADMIN_PATH (overwrite $phpbb_admin_path) + PHPBB_USE_BOARD_URL_PATH (use generate_board_url() for image paths instead of $phpbb_root_path) + PHPBB_DISABLE_ACP_EDITOR (disable ACP style editor for templates) + PHPBB_DISABLE_CONFIG_CHECK (disable ACP config.php writeable check) + + PHPBB_ACM_MEMCACHE_PORT (overwrite memcached port, default is 11211) + PHPBB_ACM_MEMCACHE_COMPRESS (overwrite memcached compress setting, default is disabled) + PHPBB_ACM_MEMCACHE_HOST (overwrite memcached host name, default is localhost) + + PHPBB_ACM_REDIS_HOST (overwrite redis host name, default is localhost) + PHPBB_ACM_REDIS_PORT (overwrite redis port, default is 6379) + PHPBB_ACM_REDIS_PASSWORD (overwrite redis password, default is empty) + PHPBB_ACM_REDIS_DB (overwrite redis default database) + + PHPBB_QA (Set board to QA-Mode, which means the updater also checks for RC-releases) + +PHPBB_USE_BOARD_URL_PATH +++++++++++++++++++++++++ + +If the ``PHPBB_USE_BOARD_URL_PATH`` constant is set to true, phpBB uses generate_board_url() (this will return the boards url with the script path included) on all instances where web-accessible images are loaded. The exact locations are: + +- /phpbb/user.php - \phpbb\user::img() +- /includes/functions_content.php - smiley_text() + +Path locations for the following template variables are affected by this too: + +- {T_ASSETS_PATH} - assets (non-style specific, static resources) +- {T_THEME_PATH} - styles/xxx/theme +- {T_TEMPLATE_PATH} - styles/xxx/template +- {T_SUPER_TEMPLATE_PATH} - styles/xxx/template +- {T_IMAGES_PATH} - images/ +- {T_SMILIES_PATH} - $config['smilies_path']/ +- {T_AVATAR_GALLERY_PATH} - $config['avatar_gallery_path']/ +- {T_ICONS_PATH} - $config['icons_path']/ +- {T_RANKS_PATH} - $config['ranks_path']/ +- {T_UPLOAD_PATH} - $config['upload_path']/ +- {T_STYLESHEET_LINK} - styles/xxx/theme/stylesheet.css +- New template variable {BOARD_URL} for the board url + script path. diff --git a/development/development/php/index.rst b/development/development/php/index.rst new file mode 100644 index 00000000..67566144 --- /dev/null +++ b/development/development/php/index.rst @@ -0,0 +1,11 @@ +PHP Coding Guidelines +====================== + +.. toctree:: + :maxdepth: 2 + + defaults + layout_guidelines + templating + character_sets_and_encodings + translation_guidelines diff --git a/development/development/php/layout_guidelines.rst b/development/development/php/layout_guidelines.rst new file mode 100644 index 00000000..ff590494 --- /dev/null +++ b/development/development/php/layout_guidelines.rst @@ -0,0 +1,903 @@ +2. Code Layout/Guidelines +========================= + +Please note that these guidelines apply to all php, html, javascript and css files. + +2.i. Variable/Function/Class Naming +----------------------------------- + +We will not be using any form of hungarian notation in our naming conventions. Many of us believe that hungarian naming is one of the primary code obfuscation techniques currently in use. + +Variable Names +++++++++++++++ + +In PHP, variable names should be in all lowercase, with words separated by an underscore, example: + +``$current_user`` is right, but ``$currentuser`` and ``$currentUser`` are not. + +In JavaScript, variable names should use camel case: + +``currentUser`` is right, but ``currentuser`` and ``current_user`` are not. + +Names should be descriptive, but concise. We don't want huge sentences as our variable names, but typing an extra couple of characters is always better than wondering what exactly a certain variable is for. + +Loop Indices +++++++++++++ + +The **only** situation where a one-character variable name is allowed is when it's the index for some looping construct. In this case, the index of the outer loop should always be ``$i``. If there's a loop inside that loop, its index should be ``$j``, followed by ``$k``, and so on. If the loop is being indexed by some already-existing variable with a meaningful name, this guideline does not apply, example: + +.. code:: php + for ($i = 0; $i < $outer_size; $i++) + { + for ($j = 0; $j < $inner_size; $j++) + { + foo($i, $j); + } + } + +Function Names +++++++++++++++ + +Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character in PHP, and camel caps in JavaScript. Function names should be prefixed with "phpbb_" and preferably have a verb in them somewhere. Good function names are ``phpbb_print_login_status()``, ``phpbb_get_user_data()``, etc. Constructor functions in JavaScript should begin with a capital letter. + +Function Arguments +++++++++++++++++++ + +Arguments are subject to the same guidelines as variable names. We don't want a bunch of functions like: ``do_stuff($a, $b, $c)``. In most cases, we'd like to be able to tell how to use a function by just looking at its declaration. + +Class Names ++++++++++++ + +Apart from following the rules for function names, all classes should meet the following conditions: + +- Every class must be defined in a separate file. +- The classes have to be located in a subdirectory of ``phpbb/``. +- Classnames must be namespaced with ``\phpbb\`` to avoid name clashes. +- Class names/namespaces have to reflect the location of the file they are defined in. The namespace must be the directory in which the file is located. So the directory names must not contain any underscores, but the filename may. +- Directories should typically be a singular noun (e.g. ``dir`` in the example below, not ``dirs``. + +So given the following example directory structure you would result in the below listed lookups + +.. code:: text + phpbb/ + class_name.php + dir/ + class_name.php + subdir/ + class_name.php + +.. code:: text + \phpbb\class_name - phpbb/class_name.php + \phpbb\dir\class_name - phpbb/dir/class_name.php + \phpbb\dir\subdir\class_name - phpbb/dir/subdir/class_name.php + +Summary ++++++++ + +The basic philosophy here is to not hurt code clarity for the sake of laziness. This has to be balanced by a little bit of common sense, though; ``phpbb_print_login_status_for_a_given_user()`` goes too far, for example -- that function would be better named ``phpbb_print_user_login_status()``, or just ``phpbb_print_login_status()``. + +Special Namings ++++++++++++++++ + +For all emoticons use the term ``smiley`` in singular and ``smilies`` in plural. For emails we use the term ``email`` (without dash between “e” and “m”). + +2.ii. Code Layout +----------------- + +Always include the braces ++++++++++++++++++++++++++ + +This is another case of being too lazy to type 2 extra characters causing problems with code clarity. Even if the body of some construct is only one line long, do not drop the braces. Just don't, examples: + +**These are all wrong:** + +.. code:: php + if (condition) do_stuff(); + + if (condition) + do_stuff(); + + while (condition) + do_stuff(); + + for ($i = 0; $i < size; $i++) + do_stuff($i); + +**These are all right:** + +.. code:: php + if (condition) + { + do_stuff(); + } + + while (condition) + { + do_stuff(); + } + + for ($i = 0; $i < size; $i++) + { + do_stuff(); + } + +Where to put the braces ++++++++++++++++++++++++ + +In PHP code, braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace, examples: + +.. code:: php + if (condition) + { + while (condition2) + { + ... + } + } + else + { + ... + } + + for ($i = 0; $i < $size; $i++) + { + ... + } + + while (condition) + { + ... + } + + function do_stuff() + { + ... + } + +Use spaces between tokens ++++++++++++++++++++++++++ + +This is another simple, easy step that helps keep code readable without much effort. Whenever you write an assignment, expression, etc.. Always leave one space between the tokens. Basically, write code as if it was English. Put spaces between variable names and operators. Don't put spaces just after an opening bracket or before a closing bracket. Don't put spaces just before a comma or a semicolon. This is best shown with a few examples, examples: + +**Each pair shows the wrong way followed by the right way:** + +.. code:: php + $i=0; + $i = 0; + + if($i<7) ... + if ($i < 7) ... + + if ( ($i < 7)&&($j > 8) ) ... + if ($i < 7 && $j > 8) ... + + do_stuff( $i, 'foo', $b ); + do_stuff($i, 'foo', $b); + + for($i=0; $i<$size; $i++) ... + for ($i = 0; $i < $size; $i++) ... + + $i=($j < $size)?0:1; + $i = ($j < $size) ? 0 : 1; + +Operator precedence ++++++++++++++++++++ + +Do you know the exact precedence of all the operators in PHP? Neither do I. Don't guess. Always make it obvious by using brackets to force the precedence of an equation so you know what it does. Remember to not over-use this, as it may harden the readability. Basically, do not enclose single expressions. Examples: + +**What's the result? who knows:** + +``$bool = ($i < 7 && $j > 8 || $k == 4);`` + +**Now you can be certain what I'm doing here:** + +``$bool = (($i < 7) && (($j < 8) || ($k == 4)));`` + +**But this one is even better, because it is easier on the eye but the intention is preserved:** + +``$bool = ($i < 7 && ($j < 8 || $k == 4));`` + +Quoting strings ++++++++++++++++ + +There are two different ways to quote strings in PHP - either with single quotes or with double quotes. The main difference is that the parser does variable interpolation in double-quoted strings, but not in single quoted strings. Because of this, you should always use single quotes unless you specifically need variable interpolation to be done on that string. This way, we can save the parser the trouble of parsing a bunch of strings where no interpolation needs to be done. + +Also, if you are using a string variable as part of a function call, you do not need to enclose that variable in quotes. Again, this will just make unnecessary work for the parser. Note, however, that nearly all of the escape sequences that exist for double-quoted strings will not work with single-quoted strings. Be careful, and feel free to break this guideline if it's making your code easier to read, examples: + +**Wrong:** + +.. code:: php + $str = "This is a really long string with no variables for the parser to find."; + + do_stuff("$str"); + +**Right:** + +.. code:: php + $str = 'This is a really long string with no variables for the parser to find.'; + + do_stuff($str); + +**Sometimes single quotes are just not right:** + +.. code:: php + $post_url = $phpbb_root_path . 'posting.' . $phpEx . '?mode=' . $mode . '&start=' . $start; + +**Double quotes are sometimes needed to not overcrowd the line with concatenations:** + +.. code:: php + $post_url = "{$phpbb_root_path}posting.$phpEx?mode=$mode&start=$start"; + +In SQL statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL formatting), else one should try to only use one method - mostly single quotes. + +Commas after every array element +++++++++++++++++++++++++++++++++ + +If an array is defined with each element on its own line, you still have to modify the previous line to add a comma when appending a new element. PHP allows for trailing (useless) commas in array definitions. These should always be used so each element including the comma can be appended with a single line. In JavaScript, do not use the trailing comma, as it causes browsers to throw errors. + +**Wrong:** + +.. code:: php + $foo = array( + 'bar' => 42, + 'boo' => 23 + ); + +**Right:** + +.. code:: php + $foo = array( + 'bar' => 42, + 'boo' => 23, + ); + +Associative array keys +++++++++++++++++++++++ + +In PHP, it's legal to use a literal string as a key to an associative array without quoting that string. We don't want to do this -- the string should always be quoted to avoid confusion. Note that this is only when we're using a literal, not when we're using a variable, examples: + +**Wrong:** + +.. code:: php + $foo = $assoc_array[blah]; + +**Right:** + +.. code:: php + $foo = $assoc_array['blah']; + +**Wrong:** + +.. code:: php + $foo = $assoc_array["$var"]; + +**Right:** + +.. code:: php + $foo = $assoc_array[$var]; + +Comments +++++++++ + +Each complex function should be preceded by a comment that tells a programmer everything they need to know to use that function. The meaning of every parameter, the expected input, and the output are required as a minimal comment. The function's behaviour in error conditions (and what those error conditions are) should also be present - but mostly included within the comment about the output. + +Especially important to document are any assumptions the code makes, or preconditions for its proper operation. Any one of the developers should be able to look at any part of the application and figure out what's going on in a reasonable amount of time. + +Avoid using ``/* */`` comment blocks for one-line comments, ``//`` should be used for one/two-liners. + +Magic numbers ++++++++++++++ + +Don't use them. Use named constants for any literal value other than obvious special cases. Basically, it's ok to check if an array has 0 elements by using the literal 0. It's not ok to assign some special meaning to a number and then use it everywhere as a literal. This hurts readability AND maintainability. The constants ``true` and `false`` should be used in place of the literals 1 and 0 -- even though they have the same values (but not type!), it's more obvious what the actual logic is when you use the named constants. Typecast variables where it is needed, do not rely on the correct variable type (PHP is currently very loose on typecasting which can lead to security problems if a developer does not keep a very close eye on it). + +Shortcut operators +++++++++++++++++++ + +The only shortcut operators that cause readability problems are the shortcut increment $i++ and decrement $j-- operators. These operators should not be used as part of an expression. They can, however, be used on their own line. Using them in expressions is just not worth the headaches when debugging, examples: + +**Wrong:** + +.. code:: php + $array[++$i] = $j; + $array[$i++] = $k; + +**Right:** + +.. code:: php + $i++; + $array[$i] = $j; + + $array[$i] = $k; + $i++; + +Inline conditionals ++++++++++++++++++++ + +Inline conditionals should only be used to do very simple things. Preferably, they will only be used to do assignments, and not for function calls or anything complex at all. They can be harmful to readability if used incorrectly, so don't fall in love with saving typing by using them, examples: + +**Bad place to use them:** + +.. code:: php + ($i < $size && $j > $size) ? do_stuff($foo) : do_stuff($bar); + +**OK place to use them:** + +.. code:: php + $min = ($i < $j) ? $i : $j; + +Don't use uninitialized variables ++++++++++++++++++++++++++++++++++ + +For phpBB3, we intend to use a higher level of run-time error reporting. This will mean that the use of an uninitialized variable will be reported as a warning. These warnings can be avoided by using the built-in isset() function to check whether a variable has been set - but preferably the variable is always existing. For checking if an array has a key set this can come in handy though, examples: + +**Wrong:** + +.. code:: php + if ($forum) ... + +**Right:** + +.. code:: php + if (isset($forum)) ... + +**Also possible:** + +.. code:: php + if (isset($forum) && $forum == 5) + +The ``empty()`` function is useful if you want to check if a variable is not set or being empty (an empty string, 0 as an integer or string, NULL, false, an empty array or a variable declared, but without a value in a class). Therefore empty should be used in favor of ``isset($array) && count($array) > 0`` - this can be written in a shorter way as ``!empty($array)``. + +Switch statements ++++++++++++++++++ + +Switch/case code blocks can get a bit long sometimes. To have some level of notice and being in-line with the opening/closing brace requirement (where they are on the same line for better readability), this also applies to switch/case code blocks and the breaks. An example: + +**Wrong:** + +.. code:: php + switch ($mode) + { + case 'mode1': + // I am doing something here + break; + case 'mode2': + // I am doing something completely different here + break; + } + +**Good:** + + +.. code:: php + switch ($mode) + { + case 'mode1': + // I am doing something here + break; + + case 'mode2': + // I am doing something completely different here + break; + + default: + // Always assume that a case was not caught + break; + } + +**Also good, if you have more code between the case and the break: + +.. code:: php + switch ($mode) + { + case 'mode1': + + // I am doing something here + + break; + + case 'mode2': + + // I am doing something completely different here + + break; + + default: + + // Always assume that a case was not caught + + break; + } + +Even if the break for the default case is not needed, it is sometimes better to include it just for readability and completeness. + +If no break is intended, please add a comment instead. An example: + +**Example with no break: + +.. code:: php + switch ($mode) + { + case 'mode1': + + // I am doing something here + + // no break here + + case 'mode2': + + // I am doing something completely different here + + break; + + default: + + // Always assume that a case was not caught + + break; + } + +Class Members ++++++++++++++ + +Use the explicit visibility qualifiers ``public``, ``private`` and ``protected`` for all properties instead of ``var``. + +Place the ``static`` qualifier before the visibility qualifiers. + +**Wrong:** + +.. code:: php + var $x; + private static function f() + +**Right:** + +.. code:: php + public $x; + static private function f() + +Constants ++++++++++ + +Prefer class constants over global constants created with ``define()``. + +2.iii. SQL/SQL Layout +--------------------- + +Common SQL Guidelines ++++++++++++++++++++++ + +All SQL should be cross-DB compatible, if DB specific SQL is used alternatives must be provided which work on all supported DB's (MySQL3/4/5, MSSQL (7.0 and 2000), PostgreSQL (8.3+), SQLite, Oracle8, ODBC (generalised if possible)). + +All SQL commands should utilise the DataBase Abstraction Layer (DBAL) + +SQL code layout ++++++++++++++++ + +SQL Statements are often unreadable without some formatting, since they tend to be big at times. Though the formatting of sql statements adds a lot to the readability of code. SQL statements should be formatted in the following way, basically writing keywords: + +.. code:: php + $sql = 'SELECT * + <-one tab->FROM ' . SOME_TABLE . ' + <-one tab->WHERE a = 1 + <-two tabs->AND (b = 2 + <-three tabs->OR b = 3) + <-one tab->ORDER BY b'; + +**Here the example with the tabs applied:** + +.. code:: php + $sql = 'SELECT * + FROM ' . SOME_TABLE . ' + WHERE a = 1 + AND (b = 2 + OR b = 3) + ORDER BY b'; + +SQL Quotes +++++++++++ + +Use double quotes where applicable. (The variables in these examples are typecasted to integers beforehand.) Examples: + +**Wrong:** + +.. code:: php + "UPDATE " . SOME_TABLE . " SET something = something_else WHERE a = $b"; + + 'UPDATE ' . SOME_TABLE . ' SET something = ' . $user_id . ' WHERE a = ' . $something; + +**Right:** + +.. code:: php + 'UPDATE ' . SOME_TABLE . " SET something = something_else WHERE a = $b"; + + 'UPDATE ' . SOME_TABLE . " SET something = $user_id WHERE a = $something"; + +In other words use single quotes where no variable substitution is required or where the variable involved shouldn't appear within double quotes. Otherwise use double quotes. + +Avoid DB specific SQL ++++++++++++++++++++++ + +The "not equals operator", as defined by the SQL:2003 standard, is "<>" + +**Wrong:** + +.. code:: php + $sql = 'SELECT * + FROM ' . SOME_TABLE . ' + WHERE a != 2'; + +**Right:** + +.. code:: php + $sql = 'SELECT * + FROM ' . SOME_TABLE . ' + WHERE a <> 2'; + +Common DBAL methods ++++++++++++++++++++ + +sql_escape() +^^^^^^^^^^^^ + +Always use ``$db->sql_escape()`` if you need to check for a string within an SQL statement (even if you are sure the variable cannot contain single quotes - never trust your input), for example: + +.. code:: php + $sql = 'SELECT * + FROM ' . SOME_TABLE . " + WHERE username = '" . $db->sql_escape($username) . "'"; + +sql_query_limit() +^^^^^^^^^^^^^^^^^ + +We do not add limit statements to the sql query, but instead use ``$db->sql_query_limit()``. You basically pass the query, the total number of lines to retrieve and the offset. + +Note: Since Oracle handles limits differently and because of how we implemented this handling you need to take special care if you use ``sql_query_limit`` with an sql query retrieving data from more than one table. + +Make sure when using something like "SELECT x.\*, y.jars" that there is not a column named jars in x; make sure that there is no overlap between an implicit column and the explicit columns. + +sql_build_array() +^^^^^^^^^^^^^^^^^ + +If you need to UPDATE or INSERT data, make use of the ``$db->sql_build_array()`` function. This function already escapes strings and checks other types, so there is no need to do this here. The data to be inserted should go into an array - ``$sql_ary`` - or directly within the statement if one or two variables needs to be inserted/updated. An example of an insert statement would be: + +.. code:: php + $sql_ary = array( + 'somedata' => $my_string, + 'otherdata' => $an_int, + 'moredata' => $another_int, + ); + + $db->sql_query('INSERT INTO ' . SOME_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + +To complete the example, this is how an update statement would look like: + +.. code:: php + $sql_ary = array( + 'somedata' => $my_string, + 'otherdata' => $an_int, + 'moredata' => $another_int, + ); + + $sql = 'UPDATE ' . SOME_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . (int) $user_id; + $db->sql_query($sql); + +The ``$db->sql_build_array()`` function supports the following modes: ``INSERT`` (example above), ``INSERT_SELECT`` (building query for ``INSERT INTO table (...) SELECT value, column ...`` statements), ``UPDATE`` (example above) and ``SELECT`` (for building WHERE statement [AND logic]). + +sql_multi_insert() +^^^^^^^^^^^^^^^^^^ + +If you want to insert multiple statements at once, please use the separate ``sql_multi_insert()`` method. An example: + +.. code:: php + $sql_ary = array(); + + $sql_ary[] = array( + 'somedata' => $my_string_1, + 'otherdata' => $an_int_1, + 'moredata' => $another_int_1, + ); + + $sql_ary[] = array( + 'somedata' => $my_string_2, + 'otherdata' => $an_int_2, + 'moredata' => $another_int_2, + ); + + $db->sql_multi_insert(SOME_TABLE, $sql_ary); + +sql_in_set() +^^^^^^^^^^^^ + +The ``$db->sql_in_set()`` function should be used for building ``IN ()`` and ``NOT IN ()`` constructs. Since (specifically) MySQL tend to be faster if for one value to be compared the ``=`` and ``<>`` operator is used, we let the DBAL decide what to do. A typical example of doing a positive match against a number of values would be: + +.. code:: php + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + +Based on the number of values in $forum_ids, the query can look differently. + +**SQL Statement if $forum_ids = array(1, 2, 3);** + +.. code:: php + SELECT FROM phpbb_forums WHERE forum_id IN (1, 2, 3) + +**SQL Statement if $forum_ids = array(1) or $forum_ids = 1** + +.. code:: php + SELECT FROM phpbb_forums WHERE forum_id = 1 + +Of course the same is possible for doing a negative match against a number of values: + +.. code:: php + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); + $db->sql_query($sql); + +Based on the number of values in $forum_ids, the query can look differently here too. + +**SQL Statement if $forum_ids = array(1, 2, 3);** + +.. code:: php + SELECT FROM phpbb_forums WHERE forum_id NOT IN (1, 2, 3) + +**SQL Statement if $forum_ids = array(1) or $forum_ids = 1** + +.. code:: php + SELECT FROM phpbb_forums WHERE forum_id <> 1 + +If the given array is empty, an error will be produced. + +sql_build_query() +^^^^^^^^^^^^^^^^^ + +The ``$db->sql_build_query()`` function is responsible for building sql statements for SELECT and SELECT DISTINCT queries if you need to JOIN on more than one table or retrieve data from more than one table while doing a JOIN. This needs to be used to make sure the resulting statement is working on all supported db's. Instead of explaining every possible combination, I will give a short example: + +.. code:: php + $sql_array = array( + 'SELECT' => 'f.*, ft.mark_time', + + 'FROM' => array( + FORUMS_WATCH_TABLE => 'fw', + FORUMS_TABLE => 'f', + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id', + ), + ), + + 'WHERE' => 'fw.user_id = ' . $user->data['user_id'] . ' + AND f.forum_id = fw.forum_id', + + 'ORDER_BY' => 'left_id', + ); + + $sql = $db->sql_build_query('SELECT', $sql_array); + +The possible first parameter for sql_build_query() is SELECT or SELECT_DISTINCT. As you can see, the logic is pretty self-explaining. For the LEFT_JOIN key, just add another array if you want to join on to tables for example. The added benefit of using this construct is that you are able to easily build the query statement based on conditions - for example the above LEFT_JOIN is only necessary if server side topic tracking is enabled; a slight adjustement would be: + +.. code:: php + $sql_array = array( + 'SELECT' => 'f.*', + + 'FROM' => array( + FORUMS_WATCH_TABLE => 'fw', + FORUMS_TABLE => 'f', + ), + + 'WHERE' => 'fw.user_id = ' . $user->data['user_id'] . ' + AND f.forum_id = fw.forum_id', + + 'ORDER_BY' => 'left_id', + ); + + if ($config['load_db_lastread']) + { + $sql_array['LEFT_JOIN'] = array( + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id', + ), + ); + + $sql_array['SELECT'] .= ', ft.mark_time '; + } + else + { + // Here we read the cookie data + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + +2.iv. Optimizations +------------------- + +Operations in loop definition: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Always try to optimize your loops if operations are going on at the comparing part, since this part is executed every time the loop is parsed through. For assignments a descriptive name should be chosen. Example: + +**On every iteration the count function is called:** + +.. code:: php + for ($i = 0; $i < count($post_data); $i++) + { + do_something(); + } + +**You are able to assign the (not changing) result within the loop itself:** + +.. code:: php + for ($i = 0, $size = count($post_data); $i < $size; $i++) + { + do_something(); + } + +Use of in_array() +^^^^^^^^^^^^^^^^^ + +Try to avoid using ``in_array()`` on huge arrays, and try to not place them into loops if the array to check consist of more than 20 entries. ``in_array()`` can be very time consuming and uses a lot of cpu processing time. For little checks it is not noticeable, but if checked against a huge array within a loop those checks alone can take several seconds. If you need this functionality, try using ``isset()`` on the arrays keys instead, actually shifting the values into keys and vice versa. A call to ``isset($array[$var])`` is a lot faster than ``in_array($var, array_keys($array))`` for example. + +2.v. General Guidelines +----------------------- + +General things +++++++++++++++ + +Never trust user input (this also applies to server variables as well as cookies). + +Try to sanitize values returned from a function. + +Try to sanitize given function variables within your function. + +The auth class should be used for all authorisation checking. + +No attempt should be made to remove any copyright information (either contained within the source or displayed interactively when the source is run/compiled), neither should the copyright information be altered in any way (it may be added to). + +Variables ++++++++++ + +Make use of the ``\phpbb\request\request`` class for everything. + +The $request->variable() method determines the type to set from the second parameter (which determines the default value too). If you need to get a scalar variable type, you need to tell this the variable() method explicitly. Examples: + +**Old method, do not use it:** + +.. code:: php + $start = (isset($HTTP_GET_VARS['start'])) ? intval($HTTP_GET_VARS['start']) : intval($HTTP_POST_VARS['start']); + $submit = (isset($HTTP_POST_VARS['submit'])) ? true : false; + +**Use request var and define a default variable (use the correct type):** + +.. code:: php + $start = $request->variable('start', 0); + $submit = $request->is_set_post('submit'); + +**$start is an int, the following use of $request->variable() therefore is not allowed:** + +.. code:: php + $start = $request->variable('start', '0'); + +**Getting an array, keys are integers, value defaults to 0:** + +.. code:: php + $mark_array = $request->variable('mark', array(0)); + +**Getting an array, keys are strings, value defaults to 0:** + +.. code:: php + $action_ary = $request->variable('action', array('' => 0)); + +Login checks/redirection +++++++++++++++++++++++++ + +To show a forum login box use ``login_forum_box($forum_data)``, else use the ``login_box()`` function. + +``$forum_data`` should contain at least the ``forum_id`` and ``forum_password`` fields. If the field ``forum_name`` is available, then it is displayed on the forum login page. + +The ``login_box()`` function can have a redirect as the first parameter. As a thumb of rule, specify an empty string if you want to redirect to the users current location, else do not add the ``$SID`` to the redirect string (for example within the ucp/login we redirect to the board index because else the user would be redirected to the login screen). + +Sensitive Operations +++++++++++++++++++++ + +For sensitive operations always let the user confirm the action. For the confirmation screens, make use of the ``confirm_box()`` function. + +Altering Operations ++++++++++++++++++++ + +For operations altering the state of the database, for instance posting, always verify the form token, unless you are already using ``confirm_box()``. To do so, make use of the ``add_form_key()`` and ``check_form_key()`` functions. + +.. code:: php + add_form_key('my_form'); + + if ($submit) + { + if (!check_form_key('my_form')) + { + trigger_error('FORM_INVALID'); + } + } + +The string passed to ``add_form_key()`` needs to match the string passed to ``check_form_key()``. Another requirement for this to work correctly is that all forms include the ``{S_FORM_TOKEN}`` template variable. + +Sessions +-------- + +Sessions should be initiated on each page, as near the top as possible using the following code: + +.. code:: php + $user->session_begin(); + $auth->acl($user->data); + $user->setup(); + +The ``$user->setup()`` call can be used to pass on additional language definition and a custom style (used in viewforum). + +Errors and messages ++++++++++++++++++++ + +All messages/errors should be outputted by calling ``trigger_error()`` using the appropriate message type and language string. Example: + +.. code:: php + trigger_error('NO_FORUM'); + +.. code:: php + trigger_error($user->lang['NO_FORUM']); + +.. code:: php + trigger_error('NO_MODE', E_USER_ERROR); + +Url formatting +++++++++++++++ + +All urls pointing to internal files need to be prepended by the ``$phpbb_root_path`` variable. Within the administration control panel all urls pointing to internal files need to be prepended by the ``$phpbb_admin_path variable. This makes sure the path is always correct and users being able to just rename the admin folder and the acp still working as intended (though some links will fail and the code need to be slightly adjusted). + +The ``append_sid()`` function from 2.0.x is available too, though it does not handle url alterations automatically. Please have a look at the code documentation if you want to get more details on how to use append_sid(). A sample call to append_sid() can look like this: + +.. code:: php + append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']) + +General function usage +++++++++++++++++++++++ + +Some of these functions are only chosen over others because of personal preference and have no benefit other than maintaining consistency throughout the code. + +Use ``strpos`` instead of ``strstr`` + +Use ``else if`` instead of ``elseif`` + +Use ``false`` (lowercase) instead of ``FALSE`` + +Use ``true`` (lowercase) instead of ``TRUE`` + +Exiting ++++++++ + +Your page should either call ``page_footer()`` in the end to trigger output through the template engine and terminate the script, or alternatively at least call the ``exit_handler()``. That call is necessary because it provides a method for external applications embedding phpBB to be called at the end of the script. + +2.vi. Restrictions on the Use of PHP +------------------------------------ + +Dynamic code execution +++++++++++++++++++++++ + +Never execute dynamic PHP code (generated or in a constant string) using any of the following PHP functions: + +- eval +- create_function +- preg_replace with the **e** modifier in the pattern + +If absolutely necessary a file should be created, and a mechanism for creating this file prior to running phpBB should be provided as a setup process. + +The e modifier in **preg_replace** can be replaced by **preg_replace_callback** and objects to encapsulate state that is needed in the callback code. + +Other functions, operators, statements and keywords: +The following PHP statements should also not be used in phpBB: + +- goto diff --git a/development/development/php/templating.rst b/development/development/php/templating.rst new file mode 100644 index 00000000..6d06a2d6 --- /dev/null +++ b/development/development/php/templating.rst @@ -0,0 +1,491 @@ +4. Templating +============= + +4.i. General Templating +----------------------- + +File naming ++++++++++++ + +Firstly templates now take the suffix ".html" rather than ".tpl". This was done simply to make the lives of some people easier wrt syntax highlighting, etc. + +Variables ++++++++++ + +All template variables should be named appropriately (using underscores for spaces), language entries should be prefixed with ``L_``, system data with ``S_``, urls with ``U_``, javascript urls with ``UA_``, language to be put in javascript statements with ``LA_``, all other variables should be presented 'as is'. + +``L_*`` template variables are automatically mapped to the corresponding language entry if the code does not set (and therefore overwrite) this variable specifically and if the language entry exists. For example ``{L_USERNAME}`` maps to ``$user->lang['USERNAME']``. The ``LA_*`` template variables are handled within the same way, but properly escaped so they can be put in javascript code. This should reduce the need to assign loads of new language variables in MODifications. + +Blocks/Loops +++++++++++++ + +The basic block level loop remains and takes the form: + +.. code:: html + <!-- BEGIN loopname --> + markup, {loopname.X_YYYYY}, etc. + <!-- END loopname --> + +A bit later loops will be explained further. To not irritate you we will explain conditionals as well as other statements first. + +Including files ++++++++++++++++ + +Something that existed in 2.0.x which no longer exists in 3.x is the ability to assign a template to a variable. This was used (for example) to output the jumpbox. Instead (perhaps better, perhaps not but certainly more flexible) we now have INCLUDE. This takes the simple form: + +.. code:: html + <!-- INCLUDE filename --> + +You will note in the 3.x templates the major sources start with <!-- INCLUDE overall_header.html --> or <!-- INCLUDE simple_header.html -->, etc. In 2.0.x control of "which" header to use was defined entirely within the code. In 3.x the template designer can output what they like. Note that you can introduce new templates (i.e. other than those in the default set) using this system and include them as you wish ... perhaps useful for a common "menu" bar or some such. No need to modify loads of files as with 2.0.x. + +Added in **3.0.6** is the ability to include a file using a template variable to specify the file, this functionality only works for root variables (i.e. not block variables). + +.. code:: html + <!-- INCLUDE {FILE_VAR} --> + +Template defined variables can also be utilised. + +.. code:: html + <!-- DEFINE $SOME_VAR = 'my_file.html' --> + <!-- INCLUDE {$SOME_VAR} --> + +PHP ++++ + +A contentious decision has seen the ability to include PHP within the template introduced. This is achieved by enclosing the PHP within relevant tags: + +.. code:: html + <!-- PHP --> + echo "hello!"; + <!-- ENDPHP --> + +You may also include PHP from an external file using: + +.. code:: html + <!-- INCLUDEPHP somefile.php --> + +it will be included and executed inline. + +.. note:: it is very much encouraged that template designers do not include PHP. The ability to include raw PHP was introduced primarily to allow end users to include banner code, etc. without modifying multiple files (as with 2.0.x). It was not intended for general use ... hence htps://www.phpbb.com will **not** make available template sets which include PHP. And by default templates will have PHP disabled (the admin will need to specifically activate PHP for a template). + +Conditionals/Control structures ++++++++++++++++++++++++++++++++ + +The most significant addition to 3.x are conditions or control structures, "if something then do this else do that". The system deployed is very similar to Smarty. This may confuse some people at first but it offers great potential and great flexibility with a little imagination. In their most simple form these constructs take the form: + +.. code:: html + <!-- IF expr --> + markup + <!-- ENDIF --> + +expr can take many forms, for example: + +.. code:: html + <!-- IF loop.S_ROW_COUNT is even --> + markup + <!-- ENDIF --> + +This will output the markup if the S_ROW_COUNT variable in the current iteration of loop is an even value (i.e. the expr is TRUE). You can use various comparison methods (standard as well as equivalent textual versions noted in square brackets) including (``not, or, and, eq, neq, is`` should be used if possible for better readability): + +.. code:: php + == [eq] + != [neq, ne] + <> (same as !=) + !== (not equivalent in value and type) + === (equivalent in value and type) + > [gt] + < [lt] + >= [gte] + <= [lte] + && [and] + || [or] + % [mod] + ! [not] + + + - + * + / + , + << (bitwise shift left) + >> (bitwise shift right) + | (bitwise or) + ^ (bitwise xor) + & (bitwise and) + ~ (bitwise not) + is (can be used to join comparison operations) + +Basic parenthesis can also be used to enforce good old BODMAS rules. Additionally some basic comparison types are defined: + +.. code:: text + even + odd + div + +Beyond the simple use of IF you can also do a sequence of comparisons using the following: + +.. code:: html + <!-- IF expr1 --> + markup + <!-- ELSEIF expr2 --> + markup + . + . + . + <!-- ELSEIF exprN --> + markup + <!-- ELSE --> + markup + <!-- ENDIF --> + +Each statement will be tested in turn and the relevant output generated when a match (if a match) is found. It is not necessary to always use ELSEIF, ELSE can be used alone to match "everything else". + +So what can you do with all this? Well take for example the colouration of rows in viewforum. In 2.0.x row colours were predefined within the source as either row color1, row color2 or row class1, row class2. In 3.x this is moved to the template, it may look a little daunting at first but remember control flows from top to bottom and it's not too difficult: + +.. code:: html + <table> + <!-- IF loop.S_ROW_COUNT is even --> + <tr class="row1"> + <!-- ELSE --> + <tr class="row2"> + <!-- ENDIF --> + <td>HELLO!</td> + </tr> + </table> + +This will cause the row cell to be output using class row1 when the row count is even, and class row2 otherwise. The S_ROW_COUNT parameter gets assigned to loops by default. Another example would be the following: + +.. code:: html + <table> + <!-- IF loop.S_ROW_COUNT > 10 --> + <tr bgcolor="#FF0000"> + <!-- ELSEIF loop.S_ROW_COUNT > 5 --> + <tr bgcolor="#00FF00"> + <!-- ELSEIF loop.S_ROW_COUNT > 2 --> + <tr bgcolor="#0000FF"> + <!-- ELSE --> + <tr bgcolor="#FF00FF"> + <!-- ENDIF --> + <td>hello!</td> + </tr> + </table> + +This will output the row cell in purple for the first two rows, blue for rows 2 to 5, green for rows 5 to 10 and red for remainder. So, you could produce a "nice" gradient effect, for example. + +What else can you do? Well, you could use IF to do common checks on for example the login state of a user: + +.. code:: html + <!-- IF S_USER_LOGGED_IN --> + markup + <!-- ENDIF --> + +This replaces the existing (fudged) method in 2.0.x using a zero length array and BEGIN/END. + +Extended syntax for Blocks/Loops +++++++++++++++++++++++++++++++++ + +Back to our loops - they had been extended with the following additions. Firstly you can set the start and end points of the loop. For example: + +.. code:: html + <!-- BEGIN loopname(2) --> + markup + <!-- END loopname --> + +Will start the loop on the third entry (note that indexes start at zero). Extensions of this are: + +``loopname(2)``: Will start the loop on the 3rd entry +``loopname(-2)``: Will start the loop two entries from the end +``loopname(3,4)``: Will start the loop on the fourth entry and end it on the fifth +``loopname(3,-4)``: Will start the loop on the fourth entry and end it four from last + +A further extension to begin is ``BEGINELSE``: + +.. code:: html + <!-- BEGIN loop --> + markup + <!-- BEGINELSE --> + markup + <!-- END loop --> + +This will cause the markup between ``BEGINELSE`` and ``END`` to be output if the loop contains no values. This is useful for forums with no topics (for example) ... in some ways it replaces "bits of" the existing "switch_" type control (the rest being replaced by conditionals). + +Another way of checking if a loop contains values is by prefixing the loops name with a dot: + +.. code:: html + <!-- IF .loop --> + <!-- BEGIN loop --> + markup + <!-- END loop --> + <!-- ELSE --> + markup + <!-- ENDIF --> + +You are even able to check the number of items within a loop by comparing it with values within the IF condition: + +.. code:: html + <!-- IF .loop > 2 --> + <!-- BEGIN loop --> + markup + <!-- END loop --> + <!-- ELSE --> + markup + <!-- ENDIF --> + +Nesting loops cause the conditionals needing prefixed with all loops from the outer one to the inner most. An illustration of this: + +.. code:: html + <!-- BEGIN firstloop --> + {firstloop.MY_VARIABLE_FROM_FIRSTLOOP} + + <!-- BEGIN secondloop --> + {firstloop.secondloop.MY_VARIABLE_FROM_SECONDLOOP} + <!-- END secondloop --> + <!-- END firstloop --> + +Sometimes it is necessary to break out of nested loops to be able to call another loop within the current iteration. This sounds a little bit confusing and it is not used very often. The following (rather complex) example shows this quite good - it also shows how you test for the first and last row in a loop (i will explain the example in detail further down): + +.. code:: html + <!-- BEGIN l_block1 --> + <!-- IF l_block1.S_SELECTED --> + <strong>{l_block1.L_TITLE}</strong> + <!-- IF S_PRIVMSGS --> + + <!-- the ! at the beginning of the loop name forces the loop to be not a nested one of l_block1 --> + <!-- BEGIN !folder --> + <!-- IF folder.S_FIRST_ROW --> + <ul class="nav"> + <!-- ENDIF --> + + <li><a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}</a></li> + + <!-- IF folder.S_LAST_ROW --> + </ul> + <!-- ENDIF --> + <!-- END !folder --> + + <!-- ENDIF --> + + <ul class="nav"> + <!-- BEGIN l_block2 --> + <li> + <!-- IF l_block1.l_block2.S_SELECTED --> + <strong>{l_block1.l_block2.L_TITLE}</strong> + <!-- ELSE --> + <a href="{l_block1.l_block2.U_TITLE}">{l_block1.l_block2.L_TITLE}</a> + <!-- ENDIF --> + </li> + <!-- END l_block2 --> + </ul> + <!-- ELSE --> + <a class="nav" href="{l_block1.U_TITLE}">{l_block1.L_TITLE}</a> + <!-- ENDIF --> + <!-- END l_block1 --> + +Let us first concentrate on this part of the example: + +.. code:: html + <!-- BEGIN l_block1 --> + <!-- IF l_block1.S_SELECTED --> + markup + <!-- ELSE --> + <a class="nav" href="{l_block1.U_TITLE}">{l_block1.L_TITLE}</a> + <!-- ENDIF --> + <!-- END l_block1 --> + +Here we open the loop ``l_block1`` and do some things if the value ``S_SELECTED`` within the current loop iteration is true, else we write the blocks link and title. Here, you see ``{l_block1.L_TITLE}`` referenced - you remember that ``L_*`` variables get automatically assigned the corresponding language entry? This is true, but not within loops. The ``L_TITLE`` variable within the loop l_block1 is assigned within the code itself. + +Let's have a closer look at the markup: + +.. code:: html + <!-- BEGIN l_block1 --> + . + . + <!-- IF S_PRIVMSGS --> + + <!-- BEGIN !folder --> + <!-- IF folder.S_FIRST_ROW --> + <ul class="nav"> + <!-- ENDIF --> + + <li><a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}</a></li> + + <!-- IF folder.S_LAST_ROW --> + </ul> + <!-- ENDIF --> + <!-- END !folder --> + + <!-- ENDIF --> + . + . + <!-- END l_block1 --> + +The ``<!-- IF S_PRIVMSGS -->`` statement clearly checks a global variable and not one within the loop, since the loop is not given here. So, if ``S_PRIVMSGS`` is true we execute the shown markup. Now, you see the ``<!-- BEGIN !folder -->`` statement. The exclamation mark is responsible for instructing the template engine to iterate through the main loop folder. So, we are now within the loop folder - with ``<!-- BEGIN folder -->`` we would have been within the loop ``l_block1.folder`` automatically as is the case with ``l_block2``: + +.. code:: html + <!-- BEGIN l_block1 --> + . + . + <ul class="nav"> + <!-- BEGIN l_block2 --> + <li> + <!-- IF l_block1.l_block2.S_SELECTED --> + <strong>{l_block1.l_block2.L_TITLE}</strong> + <!-- ELSE --> + <a href="{l_block1.l_block2.U_TITLE}">{l_block1.l_block2.L_TITLE}</a> + <!-- ENDIF --> + </li> + <!-- END l_block2 --> + </ul> + . + . + <!-- END l_block1 --> + +You see the difference? The loop l_block2 is a member of the loop l_block1 but the loop folder is a main loop. + +Now back to our folder loop: + +.. code:: html + <!-- IF folder.S_FIRST_ROW --> + <ul class="nav"> + <!-- ENDIF --> + + <li><a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}</a></li> + + <!-- IF folder.S_LAST_ROW --> + </ul> + <!-- ENDIF --> + +You may have wondered what the comparison to S_FIRST_ROW and S_LAST_ROW is about. If you haven't guessed already - it is checking for the first iteration of the loop with S_FIRST_ROW and the last iteration with S_LAST_ROW. This can come in handy quite often if you want to open or close design elements, like the above list. Let us imagine a folder loop build with three iterations, it would go this way: + +.. code:: html + <ul class="nav"> <!-- written on first iteration --> + <li>first element</li> <!-- written on first iteration --> + <li>second element</li> <!-- written on second iteration --> + <li>third element</li> <!-- written on third iteration --> + </ul> <!-- written on third iteration --> + +As you can see, all three elements are written down as well as the markup for the first iteration and the last one. Sometimes you want to omit writing the general markup - for example: + +.. code:: html + <!-- IF folder.S_FIRST_ROW --> + <ul class="nav"> + <!-- ELSEIF folder.S_LAST_ROW --> + </ul> + <!-- ELSE --> + <li><a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}</a></li> + <!-- ENDIF --> + +would result in the following markup: + +.. code:: html + <ul class="nav"> <!-- written on first iteration --> + <li>second element</li> <!-- written on second iteration --> + </ul> <!-- written on third iteration --> + +Just always remember that processing is taking place from top to bottom. + +Forms ++++++ + +If a form is used for a non-trivial operation (i.e. more than a jumpbox), then it should include the {S_FORM_TOKEN} template variable. + +.. code:: html + <form method="post" id="mcp" action="{U_POST_ACTION}"> + + <fieldset class="submit-buttons"> + <input type="reset" value="{L_RESET}" name="reset" class="button2" /> + <input type="submit" name="action[add_warning]" value="{L_SUBMIT}" class="button1" /> + {S_FORM_TOKEN} + </fieldset> + </form> + + +4.ii. Styles Tree +----------------- + +When basing a new style on an existing one, it is not necessary to provide all the template files. By declaring the base style name in the **parent** field in the **Style configuration file(cfg)**, the style can be set to reuse template files from the parent style. + +Style cfg files are simple name-value lists with the information necessary for installing a style. The important part of the style configuration file is assigning an unique name. + +The effect of doing so is that the template engine will use the template files in the new style where they exist, but fall back to files in the parent style otherwise. + +We strongly encourage the use of parent styles for styles based on the bundled styles, as it will ease the update procedure. + +.. code:: php + # General Information about this style + name = Custom Style + copyright = © phpBB Limited, 2007 + style_version = 3.2.0-b1 + phpbb_version = 3.2.0-b1 + + # Defining a different template bitfield + # template_bitfield = lNg= + + # Parent style + # Set value to empty or to this style's name if this style does not have a parent style + parent = prosilver + +4.iii. Template Events +---------------------- + +Template events must follow this format: ``<!-- EVENT event_name -->`` + +Using the above example, files named ``event_name.html`` located within extensions will be injected into the location of the event. + +Template event naming guidelines +++++++++++++++++++++++++++++++++ + +- An event name must be all lowercase, with each word separated by an underscore. +- An event name must briefly describe the location and purpose of the event. +- An event name must end with one of the following suffixes: + - ``_prepend`` - This event adds an item to the beginning of a block of related items, or adds to the beginning of individual items in a block. + - ``_append`` - This event adds an item to the end of a block of related items, or adds to the end of individual items in a block. + - ``_before`` - This event adds content directly before the specified block + - ``_after`` - This event adds content directly after the specified block + +Template event documentation +++++++++++++++++++++++++++++ + +Events must be documented in ``phpBB/docs/events.md`` in alphabetical order based on the event name. The format is as follows: + +- An event found in only one template file: + +.. code:: php + event_name + === + * Location: styles/<style_name>/template/filename.html + * Purpose: A brief description of what this event should be used for. + This may span multiple lines. + * Since: Version since when the event was added + +- An event found in multiple template files: + +.. code:: php + event_name + === + * Locations: + + first/file/path.html + + second/file/path.html + * Purpose: Same as above. + * Since: 3.2.0-b1 + +- An event that is found multiple times in a file should have the number of instances in parenthesis next to the filename. + +.. code:: php + event_name + === + * Locations: + + first/file/path.html (2) + + second/file/path.html + * Purpose: Same as above. + * Since: 3.2.0-b1 + +- An actual example event documentation: + +.. code:: php + forumlist_body_last_post_title_prepend + ==== + * Locations: + + styles/prosilver/template/forumlist_body.html + + styles/subsilver2/template/forumlist_body.html + * Purpose: Add content before the post title of the latest post in a forum on the forum list. + * Since: 3.2.0-a1 diff --git a/development/index.rst b/development/index.rst index 95cff913..298895ed 100644 --- a/development/index.rst +++ b/development/index.rst @@ -4,12 +4,13 @@ phpBB Development Documentation Contents: .. toctree:: - :maxdepth: 2 + :maxdepth: 3 + start/install + start/getting_started db/dbal development/git - development/coding_guidelines - development/index + development/coding_guidelines/index cli/index extensions/index files/index diff --git a/development/start/getting_started.rst b/development/start/getting_started.rst new file mode 100644 index 00000000..e747a429 --- /dev/null +++ b/development/start/getting_started.rst @@ -0,0 +1,178 @@ + +=============== +Getting Started +=============== + +1. Installing +============================ + +Installation, update and conversion instructions can be found in the INSTALL document in this directory. If you are intending on converting from a phpBB 2.0.x or 3.0.x installation we highly recommend that you backup any existing data before proceeding! + +Users of phpBB 3.0, 3.1 and 3.2 Beta versions cannot directly update. + +Please note that we don't support the following installation types: + +- Updates from phpBB Beta versions and lower to phpBB Release Candidates and higher +- Conversions from phpBB 2.0.x to phpBB 3.0 Beta, 3.1 Beta and 3.2 Beta versions +- phpBB 3.0 Beta, 3.1 Beta or 3.2 beta installations + +We give support for the following installation types: + +- Updates from phpBB 3.0 RC1, 3.1 RC1 and 3.2 RC1 to the latest version +- Note: if using the Automatic Update Package, updates are supported from phpBB 3.0.2 onward. To update a pre-3.0.2 installation, first - update to 3.0.2 and then update to the current version. +- Conversions from phpBB 2.0.x to the latest version +- New installations of phpBB 3.1.x - only the latest released version +- New installations of phpBB 3.2.x - only the latest released version + +2. Running +============================ + +Once installed, phpBB is easily managed via the Administration and Moderator Control Panels. If you need help or advice with phpBB, please see Section 3 below. + +2.i. Languages (Internationalisation - i18n) +-------------------------------------------- + +A number of language packs with included style localisations are available. You can find them listed in the `Language Packs`_ pages of our downloads section or from the `Language Packs`_ section of the `Customisation Database`_. + +For more information about language packs, please see: https://www.phpbb.com/languages/ + +This is the official location for all supported language sets. If you download a package from a 3rd party site you do so with the understanding that we cannot offer support. Please do not ask for support if you download a language pack from a 3rd party site. + +Installation of these packages is straightforward: simply download the required language pack, uncompress (unzip) it and via FTP transfer the included ``language`` and ``styles`` folders to the root of your board installation. The language can then be installed via the Administration Control Panel of your board: ``Customise tab -> Language management -> Language packs``. A more detailed description of the process is in the Knowledge Base article, `How to Install a Language Pack <https://www.phpbb.com/kb/article/how-to-install-a-language-pack/>`_. + +If your language is not available, please visit our `[3.2.x] Translations <https://www.phpbb.com/community/viewforum.php?f=566>`_ forum where you will find topics on translations in progress. Should you wish to volunteer to translate a language not currently available or assist in maintaining an existing language pack, you can `Apply to become a translator <https://www.phpbb.com/languages/apply.php>`_. + +2.ii. Styles +-------------------------------------------- + +Although we are rather proud of the included styles, we realise that they may not be to everyone's taste. Therefore, phpBB allows styles to be switched with relative ease. First, you need to locate and download a style you like. You can find them listed in the `Styles <https://www.phpbb.com/customise/db/styles-2/>`_ section of our `Customisation Database`_. + +For more information about styles, please see: https://www.phpbb.com/styles/ + +**Please note** that 3rd party styles downloaded for versions of phpBB2 will **not** work in phpBB3. It is also important to ensure that the style is updated to match the current version of the phpBB software you are using. + +Once you have downloaded a style, the usual next step is to unarchive (or upload the unarchived contents of) the package into your ``styles/`` directory. You then need to visit ``Administration Control Panel -> Customise tab -> Style management -> Install Styles`` where you should see the new style available. Click "Install style" to install the style. + +**Please note** that to improve efficiency, the software caches certain data. For this reason, if you create your own style or modify existing ones, please remember to purge the board cache by clicking the ``Run now`` button next to the ``Purge the cache`` option in the index page of the Administration Control Panel. You may also need to reload the page you have changed in your web browser to overcome browser caching. If the cache is not purged, you will not see your changes taking effect. + +2.iii. Extensions +-------------------------------------------- + +We are proud to have a thriving extensions community. These third party extensions to the standard phpBB software, extend its capabilities still further. You can browse through many of the extensions in the `Extensions <https://www.phpbb.com/customise/db/extensions-36>`_ section of our `Customisation Database`_. + +For more information about extensions, please see: https://www.phpbb.com/extensions + +**Please remember** that any bugs or other issues that occur after you have added any extension should **NOT** be reported to the bug tracker (see below). First disable the extension and see if the problem is resolved. Any support for an extension should only be sought in the "Discussion/Support" forum for that extension. + +Also remember that any extensions which modify the database in any way, may render upgrading your forum to future versions more difficult. + +3. Getting Help +============================ + +phpBB can sometimes seem a little daunting to new users, particularly with regards to the permission system. The first thing you should do is check the FAQ, which covers a few basic getting started questions. If you need additional help there are several places you can find it. + +3.i. phpBB Documentation +-------------------------------------------- + +Comprehensive documentation is now available on the phpBB website: + +https://www.phpbb.com/support/docs/en/3.2/ug/ + +This covers everything from installation to setting permissions and managing users. + +3.ii. Knowledge Base +-------------------------------------------- + +The Knowledge Base consists of a number of detailed articles on some common issues phpBB users may encounter while using the product. The Knowledge Base can be found at: + +https://www.phpbb.com/kb/ + +3.iii. Community Forums +-------------------------------------------- + +The phpBB project maintains a thriving community where a number of people have generously decided to donate their time to help support users. This site can be found at: + +https://www.phpbb.com/community/ + +If you do seek help via our forums please be sure to do a search before posting; if someone has experienced the issue before, then you may find that your question has already been answered. Please remember that phpBB is entirely staffed by volunteers, no one receives any compensation for the time they give, including moderators as well as developers; please be respectful and mindful when awaiting responses and receiving support. + +3.iv Internet Relay Chat +-------------------------------------------- + +Another place you may find help is our IRC channel. This operates on the Freenode IRC network, `irc.freenode.net <irc://irc.freenode.net>`_ and the channel is #phpbb and can be accessed by any decent IRC client such as mIRC, XChat, etc. Again, please do not abuse this service and be respectful of other users. + +There are other IRC channels available, please see https://www.phpbb.com/support/irc/ for the complete list. + +4. Status of this version +============================ + +This is a stable release of phpBB. The 3.2.x line is feature frozen, with point releases principally including fixes for bugs and security issues. Feature alterations and minor feature additions may be done if deemed absolutely required. The next major release will be phpBB 3.3 which is currently under development. Please do not post questions asking when 3.3 will be available, no release date has been set. + +Those interested in the development of phpBB should keep an eye on the development forums to see how things are progressing: + +http://area51.phpbb.com/phpBB/ + +Please note that the development forums should **NOT** be used to seek support for phpBB, the main community forums are the place for this. + +5. Reporting Bugs +============================ + +The phpBB developers use a bug tracking system to store, list and manage all reported bugs, it can be found at the location listed below. Please **DO NOT** post bug reports to our forums. In addition please **DO NOT** use the bug tracker for support requests. Posting such a request will only see you directed to the support forums (while taking time away from working on real bugs). + +http://tracker.phpbb.com/browse/PHPBB3 + +While we very much appreciate receiving bug reports (the more reports the more stable phpBB will be) we ask you carry out a few steps before adding new entries: + +First, determine if your bug is reproduceable; how to determine this depends on the bug in question. Only if the bug is reproduceable is it likely to be a problem with phpBB (or in some way connected). If something cannot be reproduced it may turn out to have been your hosting provider working on something, a user doing something silly, etc. Bug reports for non-reproduceable events can slow down our attempts to fix real, reproduceable issues + +Next, please read or search through the existing bug reports to see if your bug (or one very similar to it) is already listed. If it is please add to that existing bug rather than creating a new duplicate entry (all this does is slow us down). + +Check the forums (use search!) to see if people have discussed anything that sounds similar to what you are seeing. However, as noted above please **DO NOT** post your particular bug to the forum unless it's non-reproduceable or you are sure it’s related to something you have done rather than phpBB + +If no existing bug exists then please feel free to add it +If you do post a new bug (i.e. one that isn't already listed in the bug tracker) first make sure that you have logged in (your username and password are the same as for the community forums) then please include the following details: + +Your server type/version, e.g. Apache 2.2.3, IIS 7, Sambar, etc. +PHP version and mode of operation, e.g. PHP 7.1.0 as a module, PHP 7.1.0 running as CGI, etc. +DB type/version, e.g. MySQL 5.0.77, PostgreSQL 9.0.6, MSSQL Server 2000 (via ODBC), etc. +The relevant database type/version is listed within the administration control panel. + +Please be as detailed as you can in your report, and if possible, list the steps required to duplicate the problem. If you have a patch that fixes the issue, please attach it to the ticket or submit a pull request to our repository on `GitHub <https://github.com/phpbb/phpbb>`_. + +If you create a patch, it is very much appreciated (but not required) if you follow the phpBB coding guidelines. Please note that the coding guidelines are somewhat different between different versions of phpBB. For phpBB 3.2.x the coding guidelines may be found here: http://area51.phpbb.com/docs/32x/coding-guidelines.html + +Once a bug has been submitted you will be emailed any follow up comments added to it. **Please** if you are requested to supply additional information, do so! It is frustrating for us to receive bug reports, ask for additional information but get nothing. In these cases we have a policy of closing the bug, which may leave a very real problem in place. Obviously we would rather not have this situation arise. + +5.i. Security related bugs +-------------------------------------------- + +If you find a potential security related vulnerability in phpBB please **DO NOT** post it to the bug tracker, public forums, etc.! Doing so may allow unscrupulous users to take advantage of it before we have time to put a fix in place. All security related bugs should be sent to our security tracker: + +https://www.phpbb.com/security/ + +6. Overview of current bug list +============================ + +This list is not complete but does represent those bugs which may affect users on a wider scale. Other bugs listed in the tracker have typically been shown to be limited to certain setups or methods of installation, updating and/or conversions. + +Conversions may fail to complete on large boards under some hosts. +Updates may fail to complete on large update sets under some hosts. +Smilies placed directly after bbcode tags will not get parsed. Smilies always need to be separated by spaces. + +7. PHP compatibility issues +============================ + +phpBB 3.2.x takes advantage of new features added in PHP 7.1.0. We recommend that you upgrade to the latest stable release of PHP to run phpBB. The minimum version required is PHP 7.1.0 and the maximum supported version is the latest stable version of PHP. + +Please remember that running any application on a development (unstable, e.g. a beta release) version of PHP can lead to strange/unexpected results which may appear to be bugs in the application. Therefore, we recommend you upgrade to the newest stable version of PHP before running phpBB. If you are running a development version of PHP please check any bugs you find on a system running a stable release before submitting. + +This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MariaDB 5.x, PostgreSQL 8.x, Oracle 8 and SQLite 3. Versions of PHP used range from 7.1.0 to 7.2.x and 7.3.x without issues. + +7.i. Notice on PHP security issues +-------------------------------------------- + +Currently there are no known issues regarding PHP security. + + +.. _Language Packs: https://www.phpbb.com/languages/ +.. _Customisation Database: https://www.phpbb.com/customise/db/ diff --git a/development/start/install.rst b/development/start/install.rst new file mode 100644 index 00000000..2335604a --- /dev/null +++ b/development/start/install.rst @@ -0,0 +1,290 @@ +1. Quick install +================ + +If you have basic knowledge of using FTP and are sure your hosting service or server will run phpBB3 you can use these steps to quickly get started. For a more detailed explanation you should skip this and go to `2. Requirements`_ below. + +Decompress the phpBB3 archive to a local directory on your system. +Upload all the files contained in this archive (retaining the directory structure) to a web accessible directory on your server or hosting account. +Change the permissions on config.php to be writable by all (``666`` or ``-rw-rw-rw-`` within your FTP Client) +Change the permissions on the following directories to be writable by all (``777`` or ``-rwxrwxrwx`` within your FTP Client): +``store/``, ``cache/``, ``files/`` and ``images/avatars/upload/``. +Point your web browser to the location where you uploaded the phpBB3 files with the addition of ``install/app.php`` or simply ``install/``, e.g. ``http://www.example.com/phpBB3/install/app.php``, ``http://www.example.com/forum/install/``. +Click the **INSTALL** tab, follow the steps and fill out all the requested information. +Change the permissions on config.php to be writable only by yourself (``644`` or ``-rw-r--r--`` within your FTP Client) +phpBB3 should now be available, please **MAKE SURE** you read at least `6. Conversion from phpBB 2.0.x to phpBB 3.2.x`_ below for important, security related post-installation instructions, and also take note of `7. Important (security related) post-Install tasks for all installation methods`_ regarding anti-spam measures. +If you experienced problems or do not know how to proceed with any of the steps above please read the rest of this document. + +2. Requirements +============================ + +phpBB 3.2.x has a few requirements which must be met before you are able to install and use it. + +A webserver or web hosting account running on any major Operating System with support for PHP +A SQL database system, **one of**: +MySQL 3.23 or above (MySQLi supported) +MariaDB 5.1 or above +PostgreSQL 8.3+ +SQLite 3.6.15+ +MS SQL Server 2000 or above (via ODBC or the native adapter) +Oracle +PHP **7.1.0+** but less than PHP **7.3** with support for the database you intend to use. +The following PHP modules are required: +json +getimagesize() function must be enabled. +Presence of the following modules within PHP will provide access to additional features, but they are not required: +zlib Compression support +Remote FTP support +XML support +GD Support +If your server or hosting account does not meet the requirements above then you will be unable to install phpBB 3.2.x. + +3. New installation +============================ + +Installation of phpBB will vary according to your server and database. If you have shell access to your account (via telnet or ssh for example) you may want to upload the entire phpBB archive (in binary mode!) to a directory on your host and unarchive it there. + +If you do not have shell access or do not wish to use it, you will need to decompress the phpBB archive to a local directory on your system using your favourite compression program, e.g. winzip, rar, zip, etc. From there you must FTP **ALL** the files it contains (being sure to retain the directory structure and filenames) to your host. Please ensure that the cases of filenames are retained, do **NOT** force filenames to all lower or upper case as doing so will cause errors later. + +All .php, .sql, .cfg, .css, .js, .html, .htaccess and .txt files should be uploaded in **ASCII** mode, while all graphics should be uploaded in **BINARY** mode. If you are unfamiliar with what this means please refer to your FTP client documentation. In most cases this is all handled transparantly by your ftp client, but if you encounter problems later you should be sure the files were uploaded correctly as described here. + +phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see `2.i. Languages (Internationalisation - i18n)`_. + +Once all the files have been uploaded to your site, you should point your browser at this location with the addition of ``/install/``. For example, if your domain name is ``www.example.com`` and you placed the phpBB files in the directory ``/phpBB3`` off your web root you would enter ``http://www.example.com/phpBB3/install/`` or (alternatively) ``http://www.example.com/phpBB3/install/app.php`` into your browser. When you have done this, you should see the **phpBB Introduction** screen appear. + +Introduction ++++++++++++++ + +The initial screen gives you a short introduction into phpBB. It allows you to read the license phpBB is released under (General Public License v2) and provides information about how you can receive support. To start the installation, use the **INSTALL** tab. + +Requirements +++++++++++++ + +The first page you will see after starting the installation is the Requirements list. phpBB automatically checks whether everything that it needs to run properly is installed on your server. You need to have at least the minimum PHP version installed, and at least one database available to continue the installation. Also important, is that all shown folders are available and have the correct permissions. Please see the description of each section to find out whether they are optional or required for phpBB to run. If everything is in order, you can continue the installation with Start Install. + +Database settings +++++++++++++++++++ + +You now have to decide which database to use. See the `Requirements`_ section for information on which databases are supported. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need: + +- The Database Type - the database you will be using. +- The Database server hostname or DSN - the address of the database server. +- The Database server port - the port of the database server (most of the time this is not needed). +- The Database name - the name of the database on the server. +- The Database username and Database password - the login data to access the database. + +.. note:: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web. + +You don't need to change the Prefix for tables in database setting, unless you plan on using multipe phpBB installations on one database. In this case, you can use a different prefix for each installation to make it work. + +After you entered your details, you can continue with the Proceed to next step button. Now phpBB will check whether the data you entered will lead to a successful database connection and whether tables with the same prefix already exist. + +A **Could not connect** to the database error means that you didn't enter the database data correctly and it is not possible for phpBB to connect. Make sure that everything you entered is in order and try again. Again, if you are unsure about your database settings, please contact your host. + +If you installed another version of phpBB before on the same database with the same prefix, phpBB will inform you and you just need to enter a different database prefix. + +If you see the **Successful Connection** message, you can continue to the next step. + +Administrator details +++++++++++++++++++++++ + +Now you have to create your administration user. This user will have full administration access and he/she will be the first user on your forum. All fields on this page are required. You can also set the default language of your forum on this page. In a vanilla phpBB installation, we only include British English. You can download further languages from https://www.phpbb.com/, and add them before installing or later. + +Configuration file ++++++++++++++++++++ + +In this step, phpBB will try to write the configuration file automatically. The forum needs the configuration file in order to operate. It contains all the database settings, so without it, phpBB will not be able to access the database. + +Usually, writing the configuration file automatically works fine. If the file permissions are not set correctly, this process can fail. In this case, you need to upload the file manually. phpBB asks you to download the `config.php` file and tells you what to do with it. Please read the instructions carefully. After you have uploaded the file, use Done to get to the last step. If Done returns you to the same page as before, and does not return a success message, you did not upload the file correctly. + +Advanced settings +++++++++++++++++++ + +The Advanced settings allow you to set additional parameters of the board configuration. They are optional and you can always change them later. So, even if you are not sure what these settings mean, you can still proceed to the final step and finish the installation. + +If the installation was successful, you can now use the **Login** button to visit the Administration Control Panel. Congratulations, you have installed phpBB successfully. But there is still work ahead! + +If you are unable to get phpBB installed even after reading this guide, please look at the support section of the installer's introduction page to find out where you can ask for further assistance. + +At this point if you are converting from phpBB 2.0.x, you should refer to `6. Conversion from phpBB 2.0.x to phpBB 3.2.x`_ for further information. If not, you should remove the install directory from your server as you will only be able to access the Administration Control Panel whilst it is present. + +4. Updating from stable releases of phpBB 3.2.x +================================================ + +If you are currently using a stable release of phpBB, updating to this version is straightforward. You would have downloaded one of four packages and your choice determines what you need to do. +.. note:: Before updating, we heavily recommend you do a full backup of your database and existing phpBB files! If you are unsure how to achieve this please ask your hosting provider for advice. + +**Please make sure you update your phpBB source files too, even if you just run the database updater.** If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: ``php bin/phpbbcli.php --safe-mode db:migrate``. + +4.i. Full package +----------------- + +Updating using the full package is the recommended update method for boards without modifications to core phpBB files. + +First, you should make a copy of your existing ``config.php`` file; keep it in a safe place! Next, delete all the existing phpBB files, you should leave your ``files/``, ``images/`` and ``ext/`` directories in place, otherwise you will lose your file attachments, uploaded images and get errors due to missing extension files. You can leave alternative styles in place too. With this complete, you can upload the new phpBB files (see `3. New installation`_ for details if necessary). Once complete, copy back your saved ``config.php``, replacing the new one. Another method is to just **replace** the existing files with the files from the full package - though make sure you do **not** overwrite your ``config.php`` file. + +You should now got to ``/install/app.php/update`` which will display a warning: **No valid update directory was found, please make sure you uploaded the relevant files.** Beneath that warning you will see a radio button **Update database only**, just click **Submit**. Depending on your previous version this will make a number of database changes. You may receive **FAILURES** during this procedure. They should not be a cause for concern unless you see an actual **ERROR**, in which case the script will stop (in this case you should seek help via our forums or bug tracker). If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: ``php bin/phpbbcli.php --safe-mode db:migrate``. + +Once ``/install/app.php/update`` has completed, it displays the success message: **The database update was successful.** You may proceed to the Administration Control Panel and then remove the install directory as advised. + +4.ii. Changed files +------------------- + +This package is meant for those wanting to only replace the files that were changed between a previous version and the latest version. + +This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have **3.2.0** you should select the appropriate ``phpBB-3.2.1-files.zip/tar.bz2`` file. + +The directory structure has been preserved, enabling you (if you wish) to simply upload the uncompressed contents of the archive to the appropriate location on your server, i.e. simply overwrite the existing files with the new versions. Do not forget that if you have installed any modifications (MODs) these files will overwrite the originals, possibly destroying them in the process. You will need to re-add MODs to any affected file before uploading. + +As for the other update procedures, you should go to ``/install/app.php/update``, select "Update database only" and submit the page after you have finished updating the files. This will update your database schema and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: ``php bin/phpbbcli.php --safe-mode db:migrate``. + +4.iii. Patch file +----------------- + +The patch file package is for those wanting to update through the patch application, and should only be used by those who are comfortable with it. + +The patch file is one solution for those with changes in to the phpBB core files and do not want to re-add them back to all the changed files. To use this you will need command line access to a standard UNIX type **patch application**. If you do not have access to such an application, but still want to use this update approach, we strongly recommend the `4.iv. Automatic update package`_ explained below. It is also the recommended update method. + +A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is **3.2.0**, you need the ``phpBB-3.2.1-patch.zip/tar.bz2`` file. Place the correct patch in the parent directory containing the phpBB core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: ``patch -cl -d [PHPBB DIRECTORY] -p1 < [PATCH NAME]`` (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments. + +If you do get failures, you should look at using the `4.ii. Changed files` package to replace the files which failed to patch. Please note that you will need to manually re-add any MODs to these particular files. Alternatively, if you know how, you can examine the ``.rej`` files to determine what failed where and make manual adjustments to the relevant source. + +You should, of course, delete the patch file (or files) after use. As for the other update procedures, you should navigate to ``/install/app.php/update``, select "Update database only" and submit the page after you have finished updating the files. This will update your database schema and data (if appropriate) and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: ``php bin/phpbbcli.php --safe-mode db:migrate``. + +4.iv. Automatic update package +------------------------------ + +This update method is only recommended for installations with modifications to core phpBB files. This package detects changed files automatically and merges in changes if needed. + +The automatic update package will update the board from a given version to the latest version. A number of automatic update files are available, and you should choose the one that corresponds to the version of the board that you are currently running. For example, if your current version is **3.2.0**, you need the ``phpBB-3.2.0_to_3.2.1.zip/tar.bz2`` file. + +To perform the update, either follow the instructions from the **Administration Control Panel->System** Tab - this should point out that you are running an outdated version and will guide you through the update - or follow the instructions listed below. + +- Go to the `downloads page <https://www.phpbb.com/downloads/>`_ and download the latest update package listed there, matching your current version. +- Upload the uncompressed archive contents to your phpBB installation - only the ``install/`` and ``vendor/`` folders are required. Upload these folders in their entirety, retaining the file structure. +- After the install folder is present, phpBB will go offline automatically. +- Point your browser to the install directory, for example ``http://www.example.com/phpBB3/install/`` +- Choose the "Update" Tab and follow the instructions + + +4.v. All package types +---------------------- + +If you have non-English language packs installed, you may want to see if a new version has been made available. A number of missing strings may have been added which, though not essential, may be beneficial to users. Please note that at this time not all language packs have been updated so you should be prepared to periodically check for updates. + +These update methods will only update the standard style ``prosilver``, any other styles you have installed for your board will usually also need to be updated. + +5. Updating from phpBB 3.0.x/3.1x to phpBB 3.2.x +================================================== + +Updating from phpBB 3.0.x or 3.1.x to 3.2.x is just the same as `4. Updating from stable releases of phpBB 3.2.x`_ + +However you can also start with a new set of phpBB 3.2.x files. + +Delete all files **EXCEPT** for the following: +The ``config.php`` file +The ``images/`` directory +The ``files/`` directory +The ``store/`` directory +(The ``ext/`` directory +Upload the contents of the 3.2.x Full Package into your forum's directory. Make sure the root level .htaccess file is included in the upload. +Browse to ``/install/app.php/`` update +Read the notice Update database only and press **Submit** +Delete the ``install/`` directory + +6. Conversion from phpBB 2.0.x to phpBB 3.2.x +============================================= + +This paragraph explains the steps necessary to convert your existing phpBB2 installation to phpBB3. + +6.i. Requirements before converting +----------------------------------- + +Before converting, we heavily recommend you do a **full backup of your database and files!** If you are unsure how to achieve this, please ask your hosting provider for advice. You basically need to follow the instructions given for `3. New installation`_. Please **do not** overwrite any old files - install phpBB3 at a different location. + +Once you made a backup of everything and also have a brand new phpBB3 installation, you can now begin the conversion. + +Note that the conversion requires ``CREATE`` and ``DROP`` privileges for the phpBB3 database user account. + +6.ii. Converting +---------------- + +To begin the conversion, visit the ``install/`` folder of your phpBB3 installation (the same as you have done for installing). Now you will see a new tab **Convert**. Click this tab. + +As with install, the conversion is automated. Your previous 2.0.x database tables will not be changed and the original 2.0.x files will remain unaltered. The conversion is actually only filling your phpBB3 database tables and copying additional data over to your phpBB3 installation. This has the benefit that if something goes wrong, you are able to either re-run the conversion or continue a conversion, while your old board is still accessible. We really recommend that you disable your old installation while converting, else you may have inconsistent data after the conversion. + +Please note that this conversion process may take quite some time and depending on your hosting provider this may result in it failing (due to web server resource limits or other timeout issues). If this is the case, you should ask your provider if they are willing to allow the convert script to temporarily exceed their limits (be nice and they will probably be quite helpful). If your host is unwilling to increase the limits to run the convertor, please see this article for performing the conversion on your local machine: `Knowledge Base - Offline Conversions <https://www.phpbb.com/kb/article/offline-conversions/>`_ + +Once completed, your board should be immediately available. If you encountered errors, you should report the problems to our bug tracker or seek help via our forums (see `5. Reporting Bugs`_ for details). + +6.iii. Things to do after conversion +------------------------------------ + +After a successful conversion, there may be a few items you need to do - apart from checking if the installation is accessible and everything displayed correctly. + +The first thing you may want to do is to go to the administration control panel and check every configuration item within the general tab. Thereafter, you may want to adjust the forum descriptions/names if you entered HTML there. You also may want to access the other administrative sections, e.g. adjusting permissions, smilies, icons, ranks, etc. + +During the conversion, the search index is not created or transferred. This means after conversion you are not able to find any matches if you want to search for something. We recommend you rebuild your search index within **Administration Control Panel -> Maintenance -> Database -> Search Index**. + +After verifying the settings in the ACP, you can delete the install directory to enable the board. The board will stay disabled until you do so. + +Once you are pleased with your new installation, you may want to give it the name of your old installation, changing the directory name. With phpBB3 this is possible without any problems, but you may still want to check your cookie settings within the administration panel; in case your cookie path needs to be adjusted prior to renaming. + +6.iv. Common conversion problems +-------------------------------- + +**Broken non-latin characters** The conversion script assumes that the database encoding in the source phpBB2 matches the encoding defined in the ``lang_main.php`` file of the default language pack of the source installation. Edit that file to match the database's encoding and re-start the conversion procedure. + +**http 500 / white pages** The conversion is a load-heavy procedure. Restrictions imposed by some server hosting providers can cause problems. The most common causes are: values too low for the PHP settings ``memory_limit`` and ``max_execution_time``. Limits on the allowed CPU time are also a frequent cause for such errors, as are limits on the number of database queries allowed. If you cannot change such settings, then contact your hosting provider or run the conversion procedure on a different computer. The phpBB.com forums are also an excellent location to ask for support. + +**Password conversion** Due to the utf-8 based handling of passwords in phpBB3, it is not always possible to transfer all passwords. For passwords "lost in translation" the easiest workaround is to use the **I forgot my password** link on the login page. + +**Path to your former board** The convertor expects the relative path to your old board's files. So, for instance, if the old board is located at ``http://www.yourdomain.com/forum`` and the phpBB3 installation is located at ``http://www.yourdomain.com/phpBB3``, then the correct value would be ``../forum``. Note that the webserver user must be able to access the source installation's files. + +**Missing images** If your default board language's language pack does not include all images, then some images might be missing in your installation. Always use a complete language pack as default language. + +**Smilies** During the conversion you might see warnings about image files where the copying failed. This can happen if the old board's smilies have the same file names as those on the new board. Copy those files manually after the conversion, if you want to continue using the old smilies. + +7. Important (security related) post-Install tasks for all installation methods +=============================================================================== + +Once you have successfully installed phpBB you **MUST** ensure you remove the entire ``install/`` directory. Leaving the install directory in place is a very serious potential security issue which may lead to deletion or alteration of files, etc. Please note that until this directory is removed, phpBB will not operate and a warning message will be displayed. Beyond this **essential** deletion, you may also wish to delete the docs/ directory if you wish. + +With these directories deleted, you should proceed to the administration panel. Depending on how the installation completed, you may have been directed there automatically. If not, login as the administrator you specified during install/conversion and click the **Administration Control Panel** link at the bottom of any page. Ensure that details specified on the **General** tab are correct! + +7.i. Uploadable avatars +----------------------- + +phpBB supports several methods for allowing users to select their own **avatar** (an avatar is a small image generally unique to a user and displayed just below their username in posts). + +Two of these options allow users to upload an avatar from their machine or a remote location (via a URL). If you wish to enable this function you should first ensure the correct path for uploadable avatars is set in **Administration Control Panel -> General -> Board Configuration -> Avatar** settings. By default this is ``images/avatars/uploads``, but you can set it to whatever you like, just ensure the configuration setting is updated. You must also ensure this directory can be written to by the webserver. Usually this means you have to alter its permissions to allow anyone to read and write to it. Exactly how you should do this depends on your FTP client or server operating system. + +On UNIX systems, for example, you set the directory to ``a+rwx`` (or ``ugo+rwx`` or even ``777``). This can be done from a command line on your server using chmod or via your FTP client (using the **Change Permissions**, ``chmod`` or other Permissions dialog box, see your FTP client's documentation for help). Most FTP clients list permissions in the form of User (Read, Write, Execute), Group (Read, Write, Execute) and Other (Read, Write, Execute). You need to tick all of these boxes to set correct permissions. + +On Windows systems, you need to ensure the directory is not write-protected and that it has global write permissions (see your server's documentation or contact your hosting provider if you are unsure on how to achieve this). + +Please be aware that setting a directory's permissions to global write access is a potential security issue. While it is unlikely that anything nasty will occur (such as all the avatars being deleted) there are always people out there to cause trouble. Therefore you should monitor this directory and if possible make regular backups. + +7.ii. Webserver configuration +----------------------------- + +Depending on your web server, you may have to configure your server to deny web access to the ``cache/``, ``files/``, ``includes``, ``phpbb``, ``store/``, and vendor directories. This is to prevent users from accessing sensitive files. + +For **Apache** there are ``.htaccess`` files already in place to do this for the most sensitive files and folders. We do however recommend to completely deny all access to the aforementioned folders and their respective subfolders in your Apache configuration. +On **Apache 2.4**, denying access to the ``phpbb`` folder in a phpBB instance located at ``/var/www/html/`` would be accomplished by adding the following access rules to the Apache configuration file (typically ``apache.conf``): + +.. code-block:: text + <Directory /var/www/html/phpbb/*> + Require all denied + </Directory> + <Directory /var/www/html/phpbb> + Require all denied + </Directory> + +The same settings can be applied to the other mentioned directories by replacing ``phpbb`` by the respective directory name. Please note that there are differences in syntax between Apache version `2.2 <https://httpd.apache.org/docs/2.2/howto/access.html>`_ and `2.4 <https://httpd.apache.org/docs/2.4/howto/access.html>`_. + +For **Windows** based servers using **IIS** there are ``web.config`` files already in place to do this for you. For other webservers, you will have to adjust the configuration yourself. Sample files for **nginx** and **lighttpd** to help you get started may be found in the ``docs/`` directory. + +8. Anti-Spam Measures +===================== + +Like any online site that allows user input, your board could be subject to unwanted posts; often referred to as `forum spam <http://en.wikipedia.org/wiki/Forum_spam>`_. The vast majority of these attacks will be from automated computer programs known as `spambots <http://en.wikipedia.org/wiki/Spambot>`_. The attacks, generally, are not personal as the spammers are just trying to find accessible targets. phpBB has a number of anti-spam measures built in, including a range of CAPTCHAs. However, administrators are strongly urged to read and follow the advice for `Preventing Spam in phpBB <https://www.phpbb.com/support/spam/>`_ as soon as possible after completing the installation of your board. From ee54a3ea361680eed25b23311420fac95b2c7828 Mon Sep 17 00:00:00 2001 From: Michael Miday <hanakin@users.noreply.github.com> Date: Fri, 15 Mar 2019 09:21:27 -1000 Subject: [PATCH 29/98] Add html guidance --- development/development/html/guidance.rst | 140 ++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 development/development/html/guidance.rst diff --git a/development/development/html/guidance.rst b/development/development/html/guidance.rst new file mode 100644 index 00000000..fc80ecfd --- /dev/null +++ b/development/development/html/guidance.rst @@ -0,0 +1,140 @@ +Idiomatic HTMLGuidelines +================================================ + +1. Whitespace +---------------- + +Only one style should exist across the entire source of your code-base. +Always be consistent in your use of whitespace. Use whitespace to +improve readability. + +- Never mix spaces and tabs for indentation. +- Preference: ``Tabs`` + +.. tip: configure your editor to “show invisibles”. This will allow you to +eliminate end of line whitespace, eliminate unintended blank line +whitespace, and avoid polluting commits. + +2. Format +------------ + +- Always use lowercase tag and attribute names. +- Write one discrete element per line. +- Use one additional level of indentation for each nested element. +- Use valueless boolean attributes (e.g. ``checked`` rather than + ``checked="checked"``). +- Always use double quotes to quote attribute values. +- Omit the ``type`` attributes from ``link`` stylesheet, ``style`` and + ``script`` elements. +- Always include closing tags. ``<p>Some text</p>`` **NOT** ``<p>Some text`` +- Don’t include a trailing slash in self-closing elements. + +Example: + +.. code:: html + <div class="tweet"> + <a href="path/to/somewhere"> + <img src="path/to/image.png" alt=""> + </a> + <p>[tweet text]</p> + <button disabled>Reply</button> + </div> + +4. Attribute order +------------------ + +HTML attributes should be listed in an order that reflects the fact that +class names are the primary interface through which CSS and JavaScript +select elements. + +1. ``class`` +2. ``id`` +3. ``data-*`` +4. Everything else + +Example: + +.. code:: html + <a class="[value]" id="[value]" data-name="[value]" href="[url]">[text]</a> + +5. Naming +--------- + +Naming is hard, but very important. It’s a crucial part of the process +of developing a maintainable code base, and ensuring that you have a +relatively scalable interface between your HTML and CSS/JS. + +- Use clear, thoughtful, and appropriate names for HTML classes. The + names should be informative both within HTML and CSS files. +- Avoid *systematic* use of abbreviated class names. Don’t make things + difficult to understand. + +**Example with bad names:** + +.. code:: html + <div class="cb s-scr"></div> + +.. code:: css + .s-scr { + overflow: auto; + } + + .cb { + background: #000; + } + +**Example with better names:** + +.. code:: html + <div class="column-body is-scrollable"></div> + +.. code:: css + .is-scrollable { + overflow: auto; + } + + .column-body { + background: #000; + } + +6. Practical example +-------------------- + +An example of various conventions. + +.. code:: html + + <!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <title>Document + + + + + + + From 86740a77ed62038dc16d5a03d43e49ed7907345c Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Fri, 15 Mar 2019 09:29:15 -1000 Subject: [PATCH 30/98] Add html section page --- development/development/html/index.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 development/development/html/index.rst diff --git a/development/development/html/index.rst b/development/development/html/index.rst new file mode 100644 index 00000000..fae52a3c --- /dev/null +++ b/development/development/html/index.rst @@ -0,0 +1,18 @@ +HTML Coding Guidelines +====================== + +We use `HTMLHint `_ for checking the quality, linting, and ensuring consistent HTML code standards. There is a ``.htmlhintrc`` file in the root of the project, and your editor probably has a plugin available which will show you when you violate these standards. + +We employ a set of standards based on the following widely used +`Idiomatic HTML Guidelines `_ + +.. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information + +.. _PhpStorm: https://www.jetbrains.com/phpstorm/ +.. _ATOM: http://www.atom.io +.. _Editor Setup: /editor-setup + +.. toctree:: + :maxdepth: 2 + + guidelines From 37bb1aabce2f2d6ad7331e00ed52fab1cc75cfad Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Fri, 15 Mar 2019 09:29:41 -1000 Subject: [PATCH 31/98] add html page to nav --- development/development/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/development/development/index.rst b/development/development/index.rst index 7a43a197..c3d43507 100644 --- a/development/development/index.rst +++ b/development/development/index.rst @@ -17,3 +17,4 @@ These documents are automatically updated when changes are made to them. php js css + html From 85510a235355318644a24ca127408ac4c8eac49d Mon Sep 17 00:00:00 2001 From: hanakin Date: Sun, 20 Oct 2019 10:01:01 -1000 Subject: [PATCH 32/98] add line breaks to html guidance --- development/development/html/guidance.rst | 70 +++++++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/development/development/html/guidance.rst b/development/development/html/guidance.rst index fc80ecfd..62e43d70 100644 --- a/development/development/html/guidance.rst +++ b/development/development/html/guidance.rst @@ -27,7 +27,7 @@ whitespace, and avoid polluting commits. - Omit the ``type`` attributes from ``link`` stylesheet, ``style`` and ``script`` elements. - Always include closing tags. ``

Some text

`` **NOT** ``

Some text`` -- Don’t include a trailing slash in self-closing elements. +- Don’t include a trailing slash in self-closing elements. ``something`` **NOT** ``something`` Example: @@ -40,7 +40,7 @@ Example: -4. Attribute order +3. Attribute order ------------------ HTML attributes should be listed in an order that reflects the fact that @@ -57,6 +57,68 @@ Example: .. code:: html [text] +4. Line Breaks +-------------- + +We highly recommend using ``

`` **OR** ```` to wrap all blocks of text over using ``
`` to control line breaks. You are not able to stlye the ``
`` tag which limits the control of the content on a page. +Prefer the use of paragrphs or block level spans over breaks as you can not style a ``br`` tag. ``

Some text

Some More Text

`` **OR** ``Some textSome More Text`` **NOT** ``Some text
Some More Text`` + +**Example with bad formated text:** + +.. code:: html + +
+ +

+ This is a Title
+ This is a subtitle +

+ +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+

+ +
+ +**Example with good formated text:** + +.. code:: css + .subtitle { + display: block; + } + + .no-margin { + padding: 0; + margin: 0; + } + +.. code:: html + +
+ +

+ This is a Title + This is a subtitle +

+ +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+

+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +

+

+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +

+

+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+ +
+ 5. Naming --------- @@ -115,10 +177,6 @@ An example of various conventions.
- [text]
  • [text] From 7563cf561712e30b2d6369cdeb9cdd585425c70a Mon Sep 17 00:00:00 2001 From: hanakin Date: Sun, 20 Oct 2019 10:06:19 -1000 Subject: [PATCH 33/98] add recommended changes --- development/development/css/css_naming.rst | 2 +- development/development/css/index.rst | 4 ++-- development/development/html/guidance.rst | 2 +- development/development/html/index.rst | 2 +- development/development/js/index.rst | 4 ++-- development/development/php/character_set_and_encodings.rst | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/development/development/css/css_naming.rst b/development/development/css/css_naming.rst index 87723419..b711ca7a 100644 --- a/development/development/css/css_naming.rst +++ b/development/development/css/css_naming.rst @@ -155,7 +155,7 @@ This means that we can have an element elsewhere which can carry the style of `` ``data-*`` Attributes ^^^^^^^^^^^^^^^^^^^^^ -It is our preferred practice to use ``data-*`` attributes as JS hooks. ``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes since to use the same attribute as the js hook. +It is our preferred practice to use ``data-*`` attributes as JS hooks. ``data-*`` attributes, as per the spec, are typically used to store custom data private to the page or application’. however since you are already binding this attribute to your js, it makes sense to use the same attribute as the js hook. .. _ITCSS: https://www.youtube.com/watch?v=1OKZOV-iLj4 .. _SUITcss: https://suitcss.github.io/ diff --git a/development/development/css/index.rst b/development/development/css/index.rst index e441502d..3a7a7a0b 100644 --- a/development/development/css/index.rst +++ b/development/development/css/index.rst @@ -4,12 +4,12 @@ CSS Coding Guidelines We use `stylelint `_ for checking the quality, linting, and ensuring consistent CSS code standards. There is a ``.stylelintrc`` file and a ``postcss-sorting.json`` file in the root of the project, and your editor probably has a plugin available which will show you when you violate these standards. We employ a set of standards loosely based on the following widely used -`CSS Guidelines `_ +`CSS Guidelines `_ .. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information .. _PhpStorm: https://www.jetbrains.com/phpstorm/ -.. _ATOM: http://www.atom.io +.. _ATOM: https://atom.io .. _Editor Setup: /editor-setup .. toctree:: diff --git a/development/development/html/guidance.rst b/development/development/html/guidance.rst index 62e43d70..862e9463 100644 --- a/development/development/html/guidance.rst +++ b/development/development/html/guidance.rst @@ -1,4 +1,4 @@ -Idiomatic HTMLGuidelines +Idiomatic HTML Guidelines ================================================ 1. Whitespace diff --git a/development/development/html/index.rst b/development/development/html/index.rst index fae52a3c..07e4a2cc 100644 --- a/development/development/html/index.rst +++ b/development/development/html/index.rst @@ -9,7 +9,7 @@ We employ a set of standards based on the following widely used .. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information .. _PhpStorm: https://www.jetbrains.com/phpstorm/ -.. _ATOM: http://www.atom.io +.. _ATOM: https://atom.io .. _Editor Setup: /editor-setup .. toctree:: diff --git a/development/development/js/index.rst b/development/development/js/index.rst index b9bfdeeb..d29f8dc8 100644 --- a/development/development/js/index.rst +++ b/development/development/js/index.rst @@ -1,12 +1,12 @@ JavaScript Guidelines ===================== -We use `XO.js `_ for checking the quality, linting, and ensuring consistent JS code standards. Its installed via npm as a module and is configured via the ``package.json`` file in the root. Your editor probably has a plugin available which will show you when you violate these standards. ``XO.js`` is an `ESLint `_ wrapper. Its essentially a custom `config `_ for ESlint, but simplifies the use as we do not have to manitain/update the standards. This means we do not need to manage an ``eslintrc`` file. +We use `XO.js `_ for checking the quality, linting, and ensuring consistent JS code standards. Its installed via npm as a module and is configured via the ``package.json`` file in the root. Your editor probably has a plugin available which will show you when you violate these standards. ``XO.js`` is an `ESLint `_ wrapper. Its essentially a custom `config `_ for ESlint, but simplifies the use as we do not have to maintain/update the standards. This means we do not need to manage an ``eslintrc`` file. .. note:: Our editors of choice are `PhpStorm`_ & `ATOM`_ which provide useful plugins to make use of these tools. Check out the `Editor Setup`_ section of the docs for more information .. _PhpStorm: https://www.jetbrains.com/phpstorm/ -.. _ATOM: http://www.atom.io +.. _ATOM: https://atom.io .. _Editor Setup: /editor-setup .. toctree:: diff --git a/development/development/php/character_set_and_encodings.rst b/development/development/php/character_set_and_encodings.rst index 0cdad7b4..30b44869 100644 --- a/development/development/php/character_set_and_encodings.rst +++ b/development/development/php/character_set_and_encodings.rst @@ -4,7 +4,7 @@ What are Unicode, UCS and UTF-8? -------------------------------- -The `Universal Character Set (UCS) `_ described in ISO/IEC 10646 consists of a large amount of characters. Each of them has a unique name and a code point which is an integer number. `Unicode `_ - which is an industry standard - complements the Universal Character Set with further information about the characters' properties and alternative character encodings. More information on Unicode can be found on the `Unicode Consortium's website `_. One of the Unicode encodings is the `8-bit Unicode Transformation Format (UTF-8) `_. It encodes characters with up to four bytes aiming for maximum compatibility with the `American Standard Code for Information Interchange `_ which is a 7-bit encoding of a relatively small subset of the UCS. +The `Universal Character Set (UCS) `_ described in ISO/IEC 10646 consists of a large amount of characters. Each of them has a unique name and a code point which is an integer number. `Unicode `_ - which is an industry standard - complements the Universal Character Set with further information about the characters' properties and alternative character encodings. More information on Unicode can be found on the `Unicode Consortium's website `_. One of the Unicode encodings is the `8-bit Unicode Transformation Format (UTF-8) `_. It encodes characters with up to four bytes aiming for maximum compatibility with the `American Standard Code for Information Interchange `_ which is a 7-bit encoding of a relatively small subset of the UCS. phpBB's use of Unicode ++++++++++++++++++++++ From 18b0053a465fc6311ba4665f5e2ec830c15f35a1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 27 Jan 2020 20:34:31 +0100 Subject: [PATCH 34/98] Add missing header to install.rst --- development/start/install.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/development/start/install.rst b/development/start/install.rst index 2335604a..c260df00 100644 --- a/development/start/install.rst +++ b/development/start/install.rst @@ -1,3 +1,7 @@ +============ +Installation +============ + 1. Quick install ================ From 8dc6bcab033b1df4d36a570bf7ac17da13c2a677 Mon Sep 17 00:00:00 2001 From: mrgoldy Date: Mon, 17 Feb 2020 13:37:10 +0100 Subject: [PATCH 35/98] Development docs in README --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d579f89c..e258930e 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,7 @@ # phpBB Documentation -Documentation for board visitors, moderators and administrators. Can be seen online [here](http://www.phpbb.com/support/documentation/3.2/) +Documentation for board visitors, moderators and administrators. Can be seen online [here](https://www.phpbb.com/support/docs/en/3.3/ug/) +
    Documentation for developers and extension writers. Can be seen online [here](https://area51.phpbb.com/docs/dev/) ## Patches From 5dc9bcd97c673ac43c9de8d596efdb0767b11adf Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sat, 28 Mar 2020 23:21:53 -1000 Subject: [PATCH 36/98] fix index links to show coding guidelines --- development/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/index.rst b/development/index.rst index f5a9fa25..bfe1d40c 100644 --- a/development/index.rst +++ b/development/index.rst @@ -10,7 +10,7 @@ Contents: start/getting_started db/dbal development/git - development/coding_guidelines/index + development/index cli/index db/dbal extensions/index From 8d31ae1042107d50f20ae88d60c791032af7d527 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Tue, 31 Mar 2020 08:55:15 -1000 Subject: [PATCH 37/98] tweak install structure to maybe fix its rendering --- development/start/install.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/development/start/install.rst b/development/start/install.rst index c260df00..b65f99cc 100644 --- a/development/start/install.rst +++ b/development/start/install.rst @@ -19,7 +19,7 @@ phpBB3 should now be available, please **MAKE SURE** you read at least `6. Conve If you experienced problems or do not know how to proceed with any of the steps above please read the rest of this document. 2. Requirements -============================ +=============== phpBB 3.2.x has a few requirements which must be met before you are able to install and use it. @@ -43,7 +43,7 @@ GD Support If your server or hosting account does not meet the requirements above then you will be unable to install phpBB 3.2.x. 3. New installation -============================ +================ Installation of phpBB will vary according to your server and database. If you have shell access to your account (via telnet or ssh for example) you may want to upload the entire phpBB archive (in binary mode!) to a directory on your host and unarchive it there. @@ -55,18 +55,18 @@ phpBB comes supplied with British English as its standard language. However, a n Once all the files have been uploaded to your site, you should point your browser at this location with the addition of ``/install/``. For example, if your domain name is ``www.example.com`` and you placed the phpBB files in the directory ``/phpBB3`` off your web root you would enter ``http://www.example.com/phpBB3/install/`` or (alternatively) ``http://www.example.com/phpBB3/install/app.php`` into your browser. When you have done this, you should see the **phpBB Introduction** screen appear. -Introduction -+++++++++++++ +3.i. Introduction +------------------- The initial screen gives you a short introduction into phpBB. It allows you to read the license phpBB is released under (General Public License v2) and provides information about how you can receive support. To start the installation, use the **INSTALL** tab. -Requirements -++++++++++++ +3.ii. Requirements +------------------- The first page you will see after starting the installation is the Requirements list. phpBB automatically checks whether everything that it needs to run properly is installed on your server. You need to have at least the minimum PHP version installed, and at least one database available to continue the installation. Also important, is that all shown folders are available and have the correct permissions. Please see the description of each section to find out whether they are optional or required for phpBB to run. If everything is in order, you can continue the installation with Start Install. -Database settings -++++++++++++++++++ +3.iii. Database settings +------------------- You now have to decide which database to use. See the `Requirements`_ section for information on which databases are supported. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need: @@ -88,20 +88,20 @@ If you installed another version of phpBB before on the same database with the s If you see the **Successful Connection** message, you can continue to the next step. -Administrator details -++++++++++++++++++++++ +3.iv Administrator details +------------------- Now you have to create your administration user. This user will have full administration access and he/she will be the first user on your forum. All fields on this page are required. You can also set the default language of your forum on this page. In a vanilla phpBB installation, we only include British English. You can download further languages from https://www.phpbb.com/, and add them before installing or later. -Configuration file -+++++++++++++++++++ +3.v Configuration file +------------------- In this step, phpBB will try to write the configuration file automatically. The forum needs the configuration file in order to operate. It contains all the database settings, so without it, phpBB will not be able to access the database. Usually, writing the configuration file automatically works fine. If the file permissions are not set correctly, this process can fail. In this case, you need to upload the file manually. phpBB asks you to download the `config.php` file and tells you what to do with it. Please read the instructions carefully. After you have uploaded the file, use Done to get to the last step. If Done returns you to the same page as before, and does not return a success message, you did not upload the file correctly. -Advanced settings -++++++++++++++++++ +3.vi Advanced settings +------------------- The Advanced settings allow you to set additional parameters of the board configuration. They are optional and you can always change them later. So, even if you are not sure what these settings mean, you can still proceed to the final step and finish the installation. From 26b347a720d3a2295cb75253b50df8fe660afc57 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 1 Apr 2020 09:54:57 -1000 Subject: [PATCH 38/98] fix link to languages page --- development/start/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/start/install.rst b/development/start/install.rst index b65f99cc..a92dbef7 100644 --- a/development/start/install.rst +++ b/development/start/install.rst @@ -51,7 +51,7 @@ If you do not have shell access or do not wish to use it, you will need to decom All .php, .sql, .cfg, .css, .js, .html, .htaccess and .txt files should be uploaded in **ASCII** mode, while all graphics should be uploaded in **BINARY** mode. If you are unfamiliar with what this means please refer to your FTP client documentation. In most cases this is all handled transparantly by your ftp client, but if you encounter problems later you should be sure the files were uploaded correctly as described here. -phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see `2.i. Languages (Internationalisation - i18n)`_. +phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see :doc:`../language/index`. Once all the files have been uploaded to your site, you should point your browser at this location with the addition of ``/install/``. For example, if your domain name is ``www.example.com`` and you placed the phpBB files in the directory ``/phpBB3`` off your web root you would enter ``http://www.example.com/phpBB3/install/`` or (alternatively) ``http://www.example.com/phpBB3/install/app.php`` into your browser. When you have done this, you should see the **phpBB Introduction** screen appear. From 21bb24a4a67c8322e3f7aabc2cf1d955c0c038c9 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 1 Apr 2020 09:58:52 -1000 Subject: [PATCH 39/98] remove duplicate database abstraction layers link --- development/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/development/index.rst b/development/index.rst index bfe1d40c..c19af4e5 100644 --- a/development/index.rst +++ b/development/index.rst @@ -8,7 +8,6 @@ Contents: start/install start/getting_started - db/dbal development/git development/index cli/index From 9f276d6e10ba817896df4010b7fe82a589188a79 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 1 Apr 2020 10:16:46 -1000 Subject: [PATCH 40/98] update irc and add discord to match .com --- development/start/getting_started.rst | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/development/start/getting_started.rst b/development/start/getting_started.rst index e747a429..a86d9f87 100644 --- a/development/start/getting_started.rst +++ b/development/start/getting_started.rst @@ -99,9 +99,25 @@ If you do seek help via our forums please be sure to do a search before posting; 3.iv Internet Relay Chat -------------------------------------------- -Another place you may find help is our IRC channel. This operates on the Freenode IRC network, `irc.freenode.net `_ and the channel is #phpbb and can be accessed by any decent IRC client such as mIRC, XChat, etc. Again, please do not abuse this service and be respectful of other users. +Another place you may find help is our IRC channel. This operates on the Freenode IRC network, `irc.freenode.net `_ -There are other IRC channels available, please see https://www.phpbb.com/support/irc/ for the complete list. +The main phpBB IRC channel is ``#phpBB``, and it is for limited general phpBB support. +For coding discussion related to phpBB in general, to Extensions, Styles, or similar, visit ``#phpBB-Coding``. + +An IRC client such as mIRC, XChat, etc. is required to access the Freenode IRC network. Alternatively, the `freenode webchat `_ can be used to access phpBB's IRC channels. There are other IRC channels available, please see https://www.phpbb.com/support/irc/ for the complete list. Again, please do not abuse this service and be respectful of other users. + +Once you have the client up and running, type ``/server irc.freenode.net`` to connect to the freenode IRC network, and then ``/join #phpbb`` to join the phpBB IRC channel. Alternatively, try clicking the following links to start up your client and connect automatically. + +`#phpBB channel `_ +`#phpBB-Coding channel `_ + +3.v Discord +-------------------------------------------- + +phpBB is also running a Discord server for discussing phpBB core development and related topics like Extensions and Styles. Please note that only limited support can be offered. +To join the phpBB Discord server, follow this `invite link `_. + +The channels on Discord are bridged to IRC so users on IRC will see your messages posted by the phpbb-discord user while posts from IRC will be flagged with a Bot flag next to a user's name in Discord. 4. Status of this version ============================ From edae87a8a3b30c1442e1edba6d57d9be71d54f4f Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 1 Apr 2020 10:22:24 -1000 Subject: [PATCH 41/98] better link --- development/start/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/start/install.rst b/development/start/install.rst index a92dbef7..8cfa7f36 100644 --- a/development/start/install.rst +++ b/development/start/install.rst @@ -51,7 +51,7 @@ If you do not have shell access or do not wish to use it, you will need to decom All .php, .sql, .cfg, .css, .js, .html, .htaccess and .txt files should be uploaded in **ASCII** mode, while all graphics should be uploaded in **BINARY** mode. If you are unfamiliar with what this means please refer to your FTP client documentation. In most cases this is all handled transparantly by your ftp client, but if you encounter problems later you should be sure the files were uploaded correctly as described here. -phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see :doc:`../language/index`. +phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see :doc:`../start/getting_started.html#i-languages-internationalisation-i18n`. Once all the files have been uploaded to your site, you should point your browser at this location with the addition of ``/install/``. For example, if your domain name is ``www.example.com`` and you placed the phpBB files in the directory ``/phpBB3`` off your web root you would enter ``http://www.example.com/phpBB3/install/`` or (alternatively) ``http://www.example.com/phpBB3/install/app.php`` into your browser. When you have done this, you should see the **phpBB Introduction** screen appear. From 8be30d9606d1afdfbacd1ea06cae1028ba15658f Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 1 Apr 2020 11:57:15 -1000 Subject: [PATCH 42/98] fix coding guidelines tree links --- development/development/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/development/development/index.rst b/development/development/index.rst index 4fd79669..56afbd3c 100644 --- a/development/development/index.rst +++ b/development/development/index.rst @@ -15,7 +15,7 @@ These documents are automatically updated when changes are made to them. .. toctree:: :maxdepth: 2 - php - js - css - html + php/index + js/index + css/index + html/index From b46e5c45129fddcab8a070c8380f889305bf3078 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 17 Aug 2020 21:26:22 +0200 Subject: [PATCH 43/98] Resolve incorrect formatting and invalid references --- .../development/css/css_guidelines.rst | 4 +- .../development/css/css_specificity.rst | 2 +- development/development/css/css_standards.rst | 2 +- development/development/html/guidance.rst | 11 ++- development/development/html/index.rst | 2 +- development/development/js/index.rst | 2 - .../php/character_set_and_encodings.rst | 9 ++- development/development/php/defaults.rst | 12 ++- development/development/php/index.rst | 4 +- .../development/php/layout_guidelines.rst | 74 +++++++++++++++++-- development/development/php/templating.rst | 35 ++++++++- development/extensions/tutorial_modules.rst | 2 +- development/start/getting_started.rst | 6 +- development/start/install.rst | 17 +++-- 14 files changed, 151 insertions(+), 31 deletions(-) diff --git a/development/development/css/css_guidelines.rst b/development/development/css/css_guidelines.rst index 34dfc8e7..360dc52b 100644 --- a/development/development/css/css_guidelines.rst +++ b/development/development/css/css_guidelines.rst @@ -30,7 +30,7 @@ Before we discuss how we write out our rulesets, let’s first familiarize ourse The following is a ``[ruleset]`` -.. code:: css +.. code-block:: [selector], [selector] { @@ -226,7 +226,7 @@ Indenting Sass Sass provides nesting functionality. That is to say, by writing this: -.. code:: css +.. code:: .foo { color: red; diff --git a/development/development/css/css_specificity.rst b/development/development/css/css_specificity.rst index c681e24e..805ac3e4 100644 --- a/development/development/css/css_specificity.rst +++ b/development/development/css/css_specificity.rst @@ -146,7 +146,7 @@ Let’s look at an example: To style an element with a class of ``.widget-title``, we have a selector that is twice as specific as it needs to be. That means that if we want to make any modifications to ``.widget-title``, we’ll need another at-least-equally specific selector: -.. code:: css +.. code:: .widget { ... } diff --git a/development/development/css/css_standards.rst b/development/development/css/css_standards.rst index 582c71c8..cc417023 100644 --- a/development/development/css/css_standards.rst +++ b/development/development/css/css_standards.rst @@ -188,7 +188,7 @@ Low-level Oftentimes we want to comment on specific declarations (i.e. lines) in a ruleset. To do this we use a kind of reverse footnote. Here is a more complex comment detailing the larger site headers mentioned above: -.. code:: scss +.. code:: // // 1. Allow us to style box model properties. diff --git a/development/development/html/guidance.rst b/development/development/html/guidance.rst index 862e9463..fcdc9e13 100644 --- a/development/development/html/guidance.rst +++ b/development/development/html/guidance.rst @@ -12,8 +12,8 @@ improve readability. - Preference: ``Tabs`` .. tip: configure your editor to “show invisibles”. This will allow you to -eliminate end of line whitespace, eliminate unintended blank line -whitespace, and avoid polluting commits. + eliminate end of line whitespace, eliminate unintended blank line + whitespace, and avoid polluting commits. 2. Format ------------ @@ -32,6 +32,7 @@ whitespace, and avoid polluting commits. Example: .. code:: html +
    @@ -55,6 +56,7 @@ select elements. Example: .. code:: html + [text] 4. Line Breaks @@ -86,6 +88,7 @@ Prefer the use of paragrphs or block level spans over breaks as you can not styl **Example with good formated text:** .. code:: css + .subtitle { display: block; } @@ -134,9 +137,11 @@ relatively scalable interface between your HTML and CSS/JS. **Example with bad names:** .. code:: html +
    .. code:: css + .s-scr { overflow: auto; } @@ -148,9 +153,11 @@ relatively scalable interface between your HTML and CSS/JS. **Example with better names:** .. code:: html +
    .. code:: css + .is-scrollable { overflow: auto; } diff --git a/development/development/html/index.rst b/development/development/html/index.rst index 07e4a2cc..6e465235 100644 --- a/development/development/html/index.rst +++ b/development/development/html/index.rst @@ -15,4 +15,4 @@ We employ a set of standards based on the following widely used .. toctree:: :maxdepth: 2 - guidelines + guidance diff --git a/development/development/js/index.rst b/development/development/js/index.rst index d29f8dc8..a7a08b12 100644 --- a/development/development/js/index.rst +++ b/development/development/js/index.rst @@ -11,5 +11,3 @@ We use `XO.js `_ for checking the quality, linting, .. toctree:: :maxdepth: 2 - - test diff --git a/development/development/php/character_set_and_encodings.rst b/development/development/php/character_set_and_encodings.rst index 30b44869..b235e223 100644 --- a/development/development/php/character_set_and_encodings.rst +++ b/development/development/php/character_set_and_encodings.rst @@ -37,7 +37,8 @@ Case insensitive comparison of strings is no longer possible with ``strtolower`` **Bad - The strings might be the same even if strtolower differs:** -.. code: php +.. code:: php + if (strtolower($string1) == strtolower($string2)) { echo '$string1 and $string2 are equal or differ in case'; @@ -45,6 +46,7 @@ Case insensitive comparison of strings is no longer possible with ``strtolower`` **Good - Case folding is really case insensitive:** +.. code:: php if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2)) { @@ -54,4 +56,7 @@ Case insensitive comparison of strings is no longer possible with ``strtolower`` Confusables Detection +++++++++++++++++++++ -phpBB offers a special method ``utf8_clean_string`` which can be used to make sure string identifiers are unique. This method uses Normalization Form Compatibility Composition (NFKC) instead of NFC and replaces similarly looking characters with a particular representative of the equivalence class. This method is currently used for usernames and group names to avoid confusion with similarly looking names. +phpBB offers a special method ``utf8_clean_string`` which can be used to make sure string identifiers are unique. +This method uses Normalization Form Compatibility Composition (NFKC) instead of NFC and replaces similarly looking +characters with a particular representative of the equivalence class. This method is currently used for usernames and +group names to avoid confusion with similarly looking names. diff --git a/development/development/php/defaults.rst b/development/development/php/defaults.rst index af56026b..8c73446d 100644 --- a/development/development/php/defaults.rst +++ b/development/development/php/defaults.rst @@ -12,6 +12,7 @@ In order to make this as simple as possible, we will be using tabs, not spaces. Tabs in front of lines are no problem, but having them within the text can be a problem if you do not set it to the amount of spaces every one of us uses. Here is a short example of how it should look like: .. code:: php + {TAB}$mode{TAB}{TAB}= $request->variable('mode', ''); {TAB}$search_id{TAB}= $request->variable('search_id', ''); @@ -29,6 +30,7 @@ Standard header for new files: This template of the header must be included at the start of all phpBB files: .. code:: php + /** * * This file is part of the phpBB Forum Software package. @@ -59,6 +61,7 @@ Files containing inline code For those files you have to put an empty comment directly after the header to prevent the documentor assigning the header to the first code element found. .. code:: php + /** * {HEADER} */ @@ -70,12 +73,15 @@ For those files you have to put an empty comment directly after the header to pr Files containing only functions +++++++++++++++++++++++++++++++ -Do not forget to comment the functions (especially the first function following the header). Each function should have at least a comment of what this function does. For more complex functions it is recommended to document the parameters too. +Do not forget to comment the functions (especially the first function following the header). Each function should have +at least a comment of what this function does. For more complex functions it is recommended to document the parameters too. Files containing only classes +++++++++++++++++++++++++++++ -Do not forget to comment the class. Classes need a separate @package definition, it is the same as the header package name. Apart from this special case the above statement for files containing only functions needs to be applied to classes and it's methods too. +Do not forget to comment the class. Classes need a separate @package definition, it is the same as the header package +name. Apart from this special case the above statement for files containing only functions needs to be applied to +classes and it's methods too. Code following the header but only functions/classes file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -83,6 +89,7 @@ Code following the header but only functions/classes file If this case is true, the best method to avoid documentation confusions is adding an ignore command, for example: .. code:: php + /** * {HEADER} */ @@ -159,6 +166,7 @@ phpBB Styles/Templates/Themes There are some special constants application developers are able to utilize to bend some of phpBB's internal functionality to suit their needs. .. code:: php + PHPBB_MSG_HANDLER (overwrite message handler) PHPBB_DB_NEW_LINK (overwrite new_link parameter for sql_connect) PHPBB_ROOT_PATH (overwrite $phpbb_root_path) diff --git a/development/development/php/index.rst b/development/development/php/index.rst index 67566144..a0213726 100644 --- a/development/development/php/index.rst +++ b/development/development/php/index.rst @@ -7,5 +7,5 @@ PHP Coding Guidelines defaults layout_guidelines templating - character_sets_and_encodings - translation_guidelines + character_set_and_encodings +.. translation_guidelines diff --git a/development/development/php/layout_guidelines.rst b/development/development/php/layout_guidelines.rst index ff590494..7343b81b 100644 --- a/development/development/php/layout_guidelines.rst +++ b/development/development/php/layout_guidelines.rst @@ -27,6 +27,7 @@ Loop Indices The **only** situation where a one-character variable name is allowed is when it's the index for some looping construct. In this case, the index of the outer loop should always be ``$i``. If there's a loop inside that loop, its index should be ``$j``, followed by ``$k``, and so on. If the loop is being indexed by some already-existing variable with a meaningful name, this guideline does not apply, example: .. code:: php + for ($i = 0; $i < $outer_size; $i++) { for ($j = 0; $j < $inner_size; $j++) @@ -38,7 +39,7 @@ The **only** situation where a one-character variable name is allowed is when it Function Names ++++++++++++++ -Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character in PHP, and camel caps in JavaScript. Function names should be prefixed with "phpbb_" and preferably have a verb in them somewhere. Good function names are ``phpbb_print_login_status()``, ``phpbb_get_user_data()``, etc. Constructor functions in JavaScript should begin with a capital letter. +Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character in PHP, and camel caps in JavaScript. Function names should be prefixed with `phpbb_` and preferably have a verb in them somewhere. Good function names are ``phpbb_print_login_status()``, ``phpbb_get_user_data()``, etc. Constructor functions in JavaScript should begin with a capital letter. Function Arguments ++++++++++++++++++ @@ -59,6 +60,7 @@ Apart from following the rules for function names, all classes should meet the f So given the following example directory structure you would result in the below listed lookups .. code:: text + phpbb/ class_name.php dir/ @@ -67,6 +69,7 @@ So given the following example directory structure you would result in the below class_name.php .. code:: text + \phpbb\class_name - phpbb/class_name.php \phpbb\dir\class_name - phpbb/dir/class_name.php \phpbb\dir\subdir\class_name - phpbb/dir/subdir/class_name.php @@ -92,6 +95,7 @@ This is another case of being too lazy to type 2 extra characters causing proble **These are all wrong:** .. code:: php + if (condition) do_stuff(); if (condition) @@ -106,6 +110,7 @@ This is another case of being too lazy to type 2 extra characters causing proble **These are all right:** .. code:: php + if (condition) { do_stuff(); @@ -127,6 +132,7 @@ Where to put the braces In PHP code, braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace, examples: .. code:: php + if (condition) { while (condition2) @@ -162,6 +168,7 @@ This is another simple, easy step that helps keep code readable without much eff **Each pair shows the wrong way followed by the right way:** .. code:: php + $i=0; $i = 0; @@ -207,6 +214,7 @@ Also, if you are using a string variable as part of a function call, you do not **Wrong:** .. code:: php + $str = "This is a really long string with no variables for the parser to find."; do_stuff("$str"); @@ -214,6 +222,7 @@ Also, if you are using a string variable as part of a function call, you do not **Right:** .. code:: php + $str = 'This is a really long string with no variables for the parser to find.'; do_stuff($str); @@ -221,11 +230,13 @@ Also, if you are using a string variable as part of a function call, you do not **Sometimes single quotes are just not right:** .. code:: php + $post_url = $phpbb_root_path . 'posting.' . $phpEx . '?mode=' . $mode . '&start=' . $start; **Double quotes are sometimes needed to not overcrowd the line with concatenations:** .. code:: php + $post_url = "{$phpbb_root_path}posting.$phpEx?mode=$mode&start=$start"; In SQL statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL formatting), else one should try to only use one method - mostly single quotes. @@ -238,6 +249,7 @@ If an array is defined with each element on its own line, you still have to modi **Wrong:** .. code:: php + $foo = array( 'bar' => 42, 'boo' => 23 @@ -246,6 +258,7 @@ If an array is defined with each element on its own line, you still have to modi **Right:** .. code:: php + $foo = array( 'bar' => 42, 'boo' => 23, @@ -259,21 +272,25 @@ In PHP, it's legal to use a literal string as a key to an associative array with **Wrong:** .. code:: php + $foo = $assoc_array[blah]; **Right:** .. code:: php + $foo = $assoc_array['blah']; **Wrong:** .. code:: php + $foo = $assoc_array["$var"]; **Right:** .. code:: php + $foo = $assoc_array[$var]; Comments @@ -298,12 +315,14 @@ The only shortcut operators that cause readability problems are the shortcut inc **Wrong:** .. code:: php + $array[++$i] = $j; $array[$i++] = $k; **Right:** .. code:: php + $i++; $array[$i] = $j; @@ -318,11 +337,13 @@ Inline conditionals should only be used to do very simple things. Preferably, th **Bad place to use them:** .. code:: php + ($i < $size && $j > $size) ? do_stuff($foo) : do_stuff($bar); **OK place to use them:** .. code:: php + $min = ($i < $j) ? $i : $j; Don't use uninitialized variables @@ -333,16 +354,19 @@ For phpBB3, we intend to use a higher level of run-time error reporting. This wi **Wrong:** .. code:: php + if ($forum) ... **Right:** .. code:: php + if (isset($forum)) ... **Also possible:** .. code:: php + if (isset($forum) && $forum == 5) The ``empty()`` function is useful if you want to check if a variable is not set or being empty (an empty string, 0 as an integer or string, NULL, false, an empty array or a variable declared, but without a value in a class). Therefore empty should be used in favor of ``isset($array) && count($array) > 0`` - this can be written in a shorter way as ``!empty($array)``. @@ -355,6 +379,7 @@ Switch/case code blocks can get a bit long sometimes. To have some level of noti **Wrong:** .. code:: php + switch ($mode) { case 'mode1': @@ -369,6 +394,7 @@ Switch/case code blocks can get a bit long sometimes. To have some level of noti .. code:: php + switch ($mode) { case 'mode1': @@ -384,9 +410,10 @@ Switch/case code blocks can get a bit long sometimes. To have some level of noti break; } -**Also good, if you have more code between the case and the break: +**Also good, if you have more code between the case and the break:** .. code:: php + switch ($mode) { case 'mode1': @@ -412,9 +439,10 @@ Even if the break for the default case is not needed, it is sometimes better to If no break is intended, please add a comment instead. An example: -**Example with no break: +**Example with no break:** .. code:: php + switch ($mode) { case 'mode1': @@ -446,12 +474,14 @@ Place the ``static`` qualifier before the visibility qualifiers. **Wrong:** .. code:: php + var $x; private static function f() **Right:** .. code:: php + public $x; static private function f() @@ -476,6 +506,7 @@ SQL code layout SQL Statements are often unreadable without some formatting, since they tend to be big at times. Though the formatting of sql statements adds a lot to the readability of code. SQL statements should be formatted in the following way, basically writing keywords: .. code:: php + $sql = 'SELECT * <-one tab->FROM ' . SOME_TABLE . ' <-one tab->WHERE a = 1 @@ -486,6 +517,7 @@ SQL Statements are often unreadable without some formatting, since they tend to **Here the example with the tabs applied:** .. code:: php + $sql = 'SELECT * FROM ' . SOME_TABLE . ' WHERE a = 1 @@ -501,6 +533,7 @@ Use double quotes where applicable. (The variables in these examples are typecas **Wrong:** .. code:: php + "UPDATE " . SOME_TABLE . " SET something = something_else WHERE a = $b"; 'UPDATE ' . SOME_TABLE . ' SET something = ' . $user_id . ' WHERE a = ' . $something; @@ -508,6 +541,7 @@ Use double quotes where applicable. (The variables in these examples are typecas **Right:** .. code:: php + 'UPDATE ' . SOME_TABLE . " SET something = something_else WHERE a = $b"; 'UPDATE ' . SOME_TABLE . " SET something = $user_id WHERE a = $something"; @@ -522,6 +556,7 @@ The "not equals operator", as defined by the SQL:2003 standard, is "<>" **Wrong:** .. code:: php + $sql = 'SELECT * FROM ' . SOME_TABLE . ' WHERE a != 2'; @@ -529,6 +564,7 @@ The "not equals operator", as defined by the SQL:2003 standard, is "<>" **Right:** .. code:: php + $sql = 'SELECT * FROM ' . SOME_TABLE . ' WHERE a <> 2'; @@ -542,6 +578,7 @@ sql_escape() Always use ``$db->sql_escape()`` if you need to check for a string within an SQL statement (even if you are sure the variable cannot contain single quotes - never trust your input), for example: .. code:: php + $sql = 'SELECT * FROM ' . SOME_TABLE . " WHERE username = '" . $db->sql_escape($username) . "'"; @@ -561,6 +598,7 @@ sql_build_array() If you need to UPDATE or INSERT data, make use of the ``$db->sql_build_array()`` function. This function already escapes strings and checks other types, so there is no need to do this here. The data to be inserted should go into an array - ``$sql_ary`` - or directly within the statement if one or two variables needs to be inserted/updated. An example of an insert statement would be: .. code:: php + $sql_ary = array( 'somedata' => $my_string, 'otherdata' => $an_int, @@ -572,6 +610,7 @@ If you need to UPDATE or INSERT data, make use of the ``$db->sql_build_array()`` To complete the example, this is how an update statement would look like: .. code:: php + $sql_ary = array( 'somedata' => $my_string, 'otherdata' => $an_int, @@ -591,6 +630,7 @@ sql_multi_insert() If you want to insert multiple statements at once, please use the separate ``sql_multi_insert()`` method. An example: .. code:: php + $sql_ary = array(); $sql_ary[] = array( @@ -613,6 +653,7 @@ sql_in_set() The ``$db->sql_in_set()`` function should be used for building ``IN ()`` and ``NOT IN ()`` constructs. Since (specifically) MySQL tend to be faster if for one value to be compared the ``=`` and ``<>`` operator is used, we let the DBAL decide what to do. A typical example of doing a positive match against a number of values would be: .. code:: php + $sql = 'SELECT * FROM ' . FORUMS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_ids); @@ -623,16 +664,19 @@ Based on the number of values in $forum_ids, the query can look differently. **SQL Statement if $forum_ids = array(1, 2, 3);** .. code:: php + SELECT FROM phpbb_forums WHERE forum_id IN (1, 2, 3) **SQL Statement if $forum_ids = array(1) or $forum_ids = 1** .. code:: php + SELECT FROM phpbb_forums WHERE forum_id = 1 Of course the same is possible for doing a negative match against a number of values: .. code:: php + $sql = 'SELECT * FROM ' . FORUMS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); @@ -643,11 +687,13 @@ Based on the number of values in $forum_ids, the query can look differently here **SQL Statement if $forum_ids = array(1, 2, 3);** .. code:: php + SELECT FROM phpbb_forums WHERE forum_id NOT IN (1, 2, 3) **SQL Statement if $forum_ids = array(1) or $forum_ids = 1** .. code:: php + SELECT FROM phpbb_forums WHERE forum_id <> 1 If the given array is empty, an error will be produced. @@ -658,6 +704,7 @@ sql_build_query() The ``$db->sql_build_query()`` function is responsible for building sql statements for SELECT and SELECT DISTINCT queries if you need to JOIN on more than one table or retrieve data from more than one table while doing a JOIN. This needs to be used to make sure the resulting statement is working on all supported db's. Instead of explaining every possible combination, I will give a short example: .. code:: php + $sql_array = array( 'SELECT' => 'f.*, ft.mark_time', @@ -684,6 +731,7 @@ The ``$db->sql_build_query()`` function is responsible for building sql statemen The possible first parameter for sql_build_query() is SELECT or SELECT_DISTINCT. As you can see, the logic is pretty self-explaining. For the LEFT_JOIN key, just add another array if you want to join on to tables for example. The added benefit of using this construct is that you are able to easily build the query statement based on conditions - for example the above LEFT_JOIN is only necessary if server side topic tracking is enabled; a slight adjustement would be: .. code:: php + $sql_array = array( 'SELECT' => 'f.*', @@ -720,13 +768,14 @@ The possible first parameter for sql_build_query() is SELECT or SELECT_DISTINCT. ------------------- Operations in loop definition: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +++++++++++++++++++++++++++++++ Always try to optimize your loops if operations are going on at the comparing part, since this part is executed every time the loop is parsed through. For assignments a descriptive name should be chosen. Example: **On every iteration the count function is called:** .. code:: php + for ($i = 0; $i < count($post_data); $i++) { do_something(); @@ -735,6 +784,7 @@ Always try to optimize your loops if operations are going on at the comparing pa **You are able to assign the (not changing) result within the loop itself:** .. code:: php + for ($i = 0, $size = count($post_data); $i < $size; $i++) { do_something(); @@ -771,28 +821,33 @@ The $request->variable() method determines the type to set from the second param **Old method, do not use it:** .. code:: php + $start = (isset($HTTP_GET_VARS['start'])) ? intval($HTTP_GET_VARS['start']) : intval($HTTP_POST_VARS['start']); $submit = (isset($HTTP_POST_VARS['submit'])) ? true : false; **Use request var and define a default variable (use the correct type):** .. code:: php + $start = $request->variable('start', 0); $submit = $request->is_set_post('submit'); **$start is an int, the following use of $request->variable() therefore is not allowed:** .. code:: php + $start = $request->variable('start', '0'); **Getting an array, keys are integers, value defaults to 0:** .. code:: php + $mark_array = $request->variable('mark', array(0)); **Getting an array, keys are strings, value defaults to 0:** .. code:: php + $action_ary = $request->variable('action', array('' => 0)); Login checks/redirection @@ -815,6 +870,7 @@ Altering Operations For operations altering the state of the database, for instance posting, always verify the form token, unless you are already using ``confirm_box()``. To do so, make use of the ``add_form_key()`` and ``check_form_key()`` functions. .. code:: php + add_form_key('my_form'); if ($submit) @@ -833,6 +889,7 @@ Sessions Sessions should be initiated on each page, as near the top as possible using the following code: .. code:: php + $user->session_begin(); $auth->acl($user->data); $user->setup(); @@ -845,22 +902,29 @@ Errors and messages All messages/errors should be outputted by calling ``trigger_error()`` using the appropriate message type and language string. Example: .. code:: php + trigger_error('NO_FORUM'); .. code:: php + trigger_error($user->lang['NO_FORUM']); .. code:: php + trigger_error('NO_MODE', E_USER_ERROR); Url formatting ++++++++++++++ -All urls pointing to internal files need to be prepended by the ``$phpbb_root_path`` variable. Within the administration control panel all urls pointing to internal files need to be prepended by the ``$phpbb_admin_path variable. This makes sure the path is always correct and users being able to just rename the admin folder and the acp still working as intended (though some links will fail and the code need to be slightly adjusted). +All urls pointing to internal files need to be prepended by the ``$phpbb_root_path`` variable. +Within the administration control panel all urls pointing to internal files need to be prepended by the ``$phpbb_admin_path variable``. +This makes sure the path is always correct and users being able to just rename the admin folder and the acp still +working as intended (though some links will fail and the code need to be slightly adjusted). The ``append_sid()`` function from 2.0.x is available too, though it does not handle url alterations automatically. Please have a look at the code documentation if you want to get more details on how to use append_sid(). A sample call to append_sid() can look like this: .. code:: php + append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']) General function usage diff --git a/development/development/php/templating.rst b/development/development/php/templating.rst index 6d06a2d6..49b78025 100644 --- a/development/development/php/templating.rst +++ b/development/development/php/templating.rst @@ -22,6 +22,7 @@ Blocks/Loops The basic block level loop remains and takes the form: .. code:: html + markup, {loopname.X_YYYYY}, etc. @@ -34,6 +35,7 @@ Including files Something that existed in 2.0.x which no longer exists in 3.x is the ability to assign a template to a variable. This was used (for example) to output the jumpbox. Instead (perhaps better, perhaps not but certainly more flexible) we now have INCLUDE. This takes the simple form: .. code:: html + You will note in the 3.x templates the major sources start with or , etc. In 2.0.x control of "which" header to use was defined entirely within the code. In 3.x the template designer can output what they like. Note that you can introduce new templates (i.e. other than those in the default set) using this system and include them as you wish ... perhaps useful for a common "menu" bar or some such. No need to modify loads of files as with 2.0.x. @@ -41,11 +43,13 @@ You will note in the 3.x templates the major sources start with Template defined variables can also be utilised. .. code:: html + @@ -55,6 +59,7 @@ PHP A contentious decision has seen the ability to include PHP within the template introduced. This is achieved by enclosing the PHP within relevant tags: .. code:: html + echo "hello!"; @@ -62,6 +67,7 @@ A contentious decision has seen the ability to include PHP within the template i You may also include PHP from an external file using: .. code:: html + it will be included and executed inline. @@ -74,6 +80,7 @@ Conditionals/Control structures The most significant addition to 3.x are conditions or control structures, "if something then do this else do that". The system deployed is very similar to Smarty. This may confuse some people at first but it offers great potential and great flexibility with a little imagination. In their most simple form these constructs take the form: .. code:: html + markup @@ -81,6 +88,7 @@ The most significant addition to 3.x are conditions or control structures, "if s expr can take many forms, for example: .. code:: html + markup @@ -88,6 +96,7 @@ expr can take many forms, for example: This will output the markup if the S_ROW_COUNT variable in the current iteration of loop is an even value (i.e. the expr is TRUE). You can use various comparison methods (standard as well as equivalent textual versions noted in square brackets) including (``not, or, and, eq, neq, is`` should be used if possible for better readability): .. code:: php + == [eq] != [neq, ne] <> (same as !=) @@ -117,6 +126,7 @@ This will output the markup if the S_ROW_COUNT variable in the current iteration Basic parenthesis can also be used to enforce good old BODMAS rules. Additionally some basic comparison types are defined: .. code:: text + even odd div @@ -124,6 +134,7 @@ Basic parenthesis can also be used to enforce good old BODMAS rules. Additionall Beyond the simple use of IF you can also do a sequence of comparisons using the following: .. code:: html + markup @@ -142,6 +153,7 @@ Each statement will be tested in turn and the relevant output generated when a m So what can you do with all this? Well take for example the colouration of rows in viewforum. In 2.0.x row colours were predefined within the source as either row color1, row color2 or row class1, row class2. In 3.x this is moved to the template, it may look a little daunting at first but remember control flows from top to bottom and it's not too difficult: .. code:: html + @@ -155,6 +167,7 @@ So what can you do with all this? Well take for example the colouration of rows This will cause the row cell to be output using class row1 when the row count is even, and class row2 otherwise. The S_ROW_COUNT parameter gets assigned to loops by default. Another example would be the following: .. code:: html +
    @@ -174,6 +187,7 @@ This will output the row cell in purple for the first two rows, blue for rows 2 What else can you do? Well, you could use IF to do common checks on for example the login state of a user: .. code:: html + markup @@ -186,6 +200,7 @@ Extended syntax for Blocks/Loops Back to our loops - they had been extended with the following additions. Firstly you can set the start and end points of the loop. For example: .. code:: html + markup @@ -200,17 +215,19 @@ Will start the loop on the third entry (note that indexes start at zero). Extens A further extension to begin is ``BEGINELSE``: .. code:: html + markup markup -This will cause the markup between ``BEGINELSE`` and ``END`` to be output if the loop contains no values. This is useful for forums with no topics (for example) ... in some ways it replaces "bits of" the existing "switch_" type control (the rest being replaced by conditionals). +This will cause the markup between ``BEGINELSE`` and ``END`` to be output if the loop contains no values. This is useful for forums with no topics (for example) ... in some ways it replaces "bits of" the existing `switch_` type control (the rest being replaced by conditionals). Another way of checking if a loop contains values is by prefixing the loops name with a dot: .. code:: html + markup @@ -222,6 +239,7 @@ Another way of checking if a loop contains values is by prefixing the loops name You are even able to check the number of items within a loop by comparing it with values within the IF condition: .. code:: html + markup @@ -233,6 +251,7 @@ You are even able to check the number of items within a loop by comparing it wit Nesting loops cause the conditionals needing prefixed with all loops from the outer one to the inner most. An illustration of this: .. code:: html + {firstloop.MY_VARIABLE_FROM_FIRSTLOOP} @@ -244,6 +263,7 @@ Nesting loops cause the conditionals needing prefixed with all loops from the ou Sometimes it is necessary to break out of nested loops to be able to call another loop within the current iteration. This sounds a little bit confusing and it is not used very often. The following (rather complex) example shows this quite good - it also shows how you test for the first and last row in a loop (i will explain the example in detail further down): .. code:: html + {l_block1.L_TITLE} @@ -283,6 +303,7 @@ Sometimes it is necessary to break out of nested loops to be able to call anothe Let us first concentrate on this part of the example: .. code:: html + markup @@ -296,6 +317,7 @@ Here we open the loop ``l_block1`` and do some things if the value ``S_SELECTED` Let's have a closer look at the markup: .. code:: html + . . @@ -321,6 +343,7 @@ Let's have a closer look at the markup: The ```` statement clearly checks a global variable and not one within the loop, since the loop is not given here. So, if ``S_PRIVMSGS`` is true we execute the shown markup. Now, you see the ```` statement. The exclamation mark is responsible for instructing the template engine to iterate through the main loop folder. So, we are now within the loop folder - with ```` we would have been within the loop ``l_block1.folder`` automatically as is the case with ``l_block2``: .. code:: html + . . @@ -344,6 +367,7 @@ You see the difference? The loop l_block2 is a member of the loop l_block1 but t Now back to our folder loop: .. code:: html +
    - - - - - - - -
    HELLO!
    +You can also use parentheses to group expressions and enforce operator precedence. -This will cause the row cell to be output using class row1 when the row count is even, and class row2 otherwise. The S_ROW_COUNT parameter gets assigned to loops by default. Another example would be the following: +Twig provides special tests for common checks: -.. code:: html +.. code-block:: text - - - - - - - - - - - - -
    hello!
    + even, odd, divisible by, defined, iterable, empty, null, same as -This will output the row cell in purple for the first two rows, blue for rows 2 to 5, green for rows 5 to 10 and red for remainder. So, you could produce a "nice" gradient effect, for example. +For example: -What else can you do? Well, you could use IF to do common checks on for example the login state of a user: +.. code-block:: twig -.. code:: html + {% if loop.index is divisible by(3) %} + markup + {% endif %} - - markup - +Twig also supports `if`/`elseif`/`else` chains: -This replaces the existing (fudged) method in 2.0.x using a zero length array and BEGIN/END. +.. code-block:: twig -Extended syntax for Blocks/Loops -++++++++++++++++++++++++++++++++ + {% if expr1 %} + markup + {% elseif expr2 %} + markup + {% else %} + markup + {% endif %} -Back to our loops - they had been extended with the following additions. Firstly you can set the start and end points of the loop. For example: +Each condition is checked in order, and the first matching block is rendered. -.. code:: html +Here are some practical examples: - - markup - +**Row coloration in a table:** -Will start the loop on the third entry (note that indexes start at zero). Extensions of this are: +.. code-block:: twig -``loopname(2)``: Will start the loop on the 3rd entry -``loopname(-2)``: Will start the loop two entries from the end -``loopname(3,4)``: Will start the loop on the fourth entry and end it on the fifth -``loopname(3,-4)``: Will start the loop on the fourth entry and end it four from last + + {% for row in rows %} + {% if loop.index is even %} + + {% else %} + + {% endif %} + + + {% endfor %} +
    HELLO!
    -A further extension to begin is ``BEGINELSE``: +This will use `row1` for even rows and `row2` for odd rows. -.. code:: html +**Gradient effect based on row count:** - - markup - - markup - +.. code-block:: twig -This will cause the markup between ``BEGINELSE`` and ``END`` to be output if the loop contains no values. This is useful for forums with no topics (for example) ... in some ways it replaces "bits of" the existing `switch_` type control (the rest being replaced by conditionals). + + {% for row in rows %} + {% if loop.index > 10 %} + + {% elseif loop.index > 5 %} + + {% elseif loop.index > 2 %} + + {% else %} + + {% endif %} + + + {% endfor %} +
    hello!
    -Another way of checking if a loop contains values is by prefixing the loops name with a dot: +This will output different background colors depending on the row index. -.. code:: html +**Checking user login state:** - - - markup - - - markup - +.. code-block:: twig -You are even able to check the number of items within a loop by comparing it with values within the IF condition: + {% if S_USER_LOGGED_IN %} + markup + {% endif %} -.. code:: html +.. seealso:: - - - markup - - - markup - + - `Twig for Template Designers - Control Structures `_ + - `Twig for Template Designers - Operators `_ -Nesting loops cause the conditionals needing prefixed with all loops from the outer one to the inner most. An illustration of this: +Extended syntax for Blocks/Loops +++++++++++++++++++++++++++++++++ -.. code:: html +Twig provides powerful features for working with loops, including setting start and end points, handling empty loops, and working with nested loops. - - {firstloop.MY_VARIABLE_FROM_FIRSTLOOP} +**Setting start and end points of a loop:** - - {firstloop.secondloop.MY_VARIABLE_FROM_SECONDLOOP} - - +You can use the `slice` filter to control which items are iterated over: -Sometimes it is necessary to break out of nested loops to be able to call another loop within the current iteration. This sounds a little bit confusing and it is not used very often. The following (rather complex) example shows this quite good - it also shows how you test for the first and last row in a loop (i will explain the example in detail further down): +.. code-block:: twig -.. code:: html + {# Start loop on the third entry (index 2) #} + {% for item in loopname|slice(2) %} + {{ item }} + {% endfor %} - - - {l_block1.L_TITLE} - - - - - - - - - - - - - - {l_block1.L_TITLE} - - - -Let us first concentrate on this part of the example: + {# Start two entries from the end #} + {% for item in loopname|slice(-2) %} + {{ item }} + {% endfor %} -.. code:: html + {# Start at index 3 and end at index 4 (2 items) #} + {% for item in loopname|slice(3, 2) %} + {{ item }} + {% endfor %} - - - markup - - {l_block1.L_TITLE} - - + {# Start at index 3 and end four from last #} + {% for item in loopname|slice(3, loopname|length - 3 - 4) %} + {{ item }} + {% endfor %} -Here we open the loop ``l_block1`` and do some things if the value ``S_SELECTED`` within the current loop iteration is true, else we write the blocks link and title. Here, you see ``{l_block1.L_TITLE}`` referenced - you remember that ``L_*`` variables get automatically assigned the corresponding language entry? This is true, but not within loops. The ``L_TITLE`` variable within the loop l_block1 is assigned within the code itself. +**Handling empty loops:** -Let's have a closer look at the markup: +Twig provides the `else` block for loops: -.. code:: html +.. code-block:: twig - - . - . - + {% for item in loop %} + {{ item }} + {% else %} + No items found. + {% endfor %} - - - - - +.. code-block:: twig - - . - . - + {% if loop|length > 0 %} + {% for item in loop %} + {{ item }} + {% endfor %} + {% else %} + No items found. + {% endif %} -The ```` statement clearly checks a global variable and not one within the loop, since the loop is not given here. So, if ``S_PRIVMSGS`` is true we execute the shown markup. Now, you see the ```` statement. The exclamation mark is responsible for instructing the template engine to iterate through the main loop folder. So, we are now within the loop folder - with ```` we would have been within the loop ``l_block1.folder`` automatically as is the case with ``l_block2``: +Or simply use the `else` block as above. -.. code:: html +**Checking the number of items in a loop:** - - . - . - - . - . - - -You see the difference? The loop l_block2 is a member of the loop l_block1 but the loop folder is a main loop. - -Now back to our folder loop: +.. code-block:: twig -.. code:: html + {% if loop|length > 2 %} + {% for item in loop %} + {{ item }} + {% endfor %} + {% else %} + Not enough items. + {% endif %} - - - +.. code-block:: html -You may have wondered what the comparison to S_FIRST_ROW and S_LAST_ROW is about. If you haven't guessed already - it is checking for the first iteration of the loop with S_FIRST_ROW and the last iteration with S_LAST_ROW. This can come in handy quite often if you want to open or close design elements, like the above list. Let us imagine a folder loop build with three iterations, it would go this way: + {% for first in firstloop %} + {{ first.MY_VARIABLE_FROM_FIRSTLOOP }} -.. code:: html + {% for second in first.secondloop %} + {{ second.MY_VARIABLE_FROM_SECONDLOOP }} + {% endfor %} + {% endfor %} - +**Breaking out of nested loops and working with special variables:** -As you can see, all three elements are written down as well as the markup for the first iteration and the last one. Sometimes you want to omit writing the general markup - for example: +Twig does not support breaking out of multiple nested loops directly, and child loops will not be directly interpreted as child loop inside `for` statements. +It is possible to use the `loop` variable to access the current loop's properties, such as `loop.index`, `loop.length`, and `loop.first`. This will however only work for the current loop, not for parent loops. -.. code:: html +.. code-block:: html - - - -
  • {folder.FOLDER_NAME}
  • - + {% for l_block1 in l_block1_list %} + {% if l_block1.S_SELECTED %} + {{ l_block1.L_TITLE }} + {% if S_PRIVMSGS %} + + {% endif %} - + + {% else %} + {{ l_block1.L_TITLE }} + {% endif %} + {% endfor %} + +**Checking for first and last iteration:** + +Use `loop.first` and `loop.last`: + +.. code-block:: html + + {% for folder in folders %} + {% if loop.first %} + + {% endif %} + {% endfor %} + +**Alternative: Only output markup for certain iterations:** + +.. code-block:: html + + {% for folder in folders %} + {% if loop.first %} + + {% else %} +
  • {{ folder.FOLDER_NAME }}
  • + {% endif %} + {% endfor %} Just always remember that processing is taking place from top to bottom. Forms +++++ -If a form is used for a non-trivial operation (i.e. more than a jumpbox), then it should include the {S_FORM_TOKEN} template variable. +If a form is used for a non-trivial operation (i.e. more than a jumpbox), then it **SHALL** include the ``{{ S_FORM_TOKEN }}`` template variable. .. code:: html - +
    - - - {S_FORM_TOKEN} + + + {{ S_FORM_TOKEN }}
    @@ -430,36 +404,85 @@ If a form is used for a non-trivial operation (i.e. more than a jumpbox), then i 4.ii. Styles Tree ----------------- -When basing a new style on an existing one, it is not necessary to provide all the template files. By declaring the base style name in the **parent** field in the **Style configuration file(cfg)**, the style can be set to reuse template files from the parent style. - -Style cfg files are simple name-value lists with the information necessary for installing a style. The important part of the style configuration file is assigning an unique name. +Style configuration ``composer.json`` files are derived from the standard `composer` file format, but with a few additional fields specific to phpBB styles. +An important part of the style is assigning a unique name both in the ``name`` field and in the ``display-name`` field in the ``extra`` section of the ``composer.json``: + +.. code:: json + + { + "name": "phpbb/phpbb-style-prosilver", + "description": "phpBB Forum Software default style", + "type": "phpbb-style", + "version": "4.0.0-a1-dev", + "homepage": "https://www.phpbb.com", + "license": "GPL-2.0", + "authors": [ + { + "name": "phpBB Limited", + "email": "operations@phpbb.com", + "homepage": "https://www.phpbb.com/go/authors" + } + ], + "support": { + "issues": "https://tracker.phpbb.com", + "forum": "https://www.phpbb.com/community/", + "docs": "https://www.phpbb.com/support/docs/", + "irc": "irc://irc.libera.chat/phpbb", + "chat": "https://www.phpbb.com/support/chat/" + }, + "extra": { + "display-name": "prosilver", + "phpbb-version": "4.0.0-a1-dev", + "parent-style": "" + } + } + +When basing a new style on an existing one, it is not necessary to provide all the template files. +By declaring the base style name in the **parent** field in the **Style configuration file (composer.json)**, the style can be set to reuse template files from the parent style: + +.. code:: json + + { + "name": "acme-author/my-custom-style", + "description": "My custom style based on prosilver", + "type": "phpbb-style", + "version": "1.0.0", + "homepage": "https://www.some-site.com", + "license": "GPL-2.0", + "authors": [ + { + "name": "ACME Author", + "email": "acme@some-site.com", + "homepage": "https://www.some-site.com" + } + ], + "extra": { + "display-name": "My Custom Style Acme Style", + "phpbb-version": "4.0.0", + "parent-style": "prosilver" + } + } The effect of doing so is that the template engine will use the template files in the new style where they exist, but fall back to files in the parent style otherwise. +In the above example, if the new style does not have a file named ``overall_header.html``, the template engine will use the one from the ``prosilver`` style. We strongly encourage the use of parent styles for styles based on the bundled styles, as it will ease the update procedure. -.. code:: php - - # General Information about this style - name = Custom Style - copyright = © phpBB Limited, 2007 - style_version = 3.2.0-b1 - phpbb_version = 3.2.0-b1 +.. note:: - # Defining a different template bitfield - # template_bitfield = lNg= - - # Parent style - # Set value to empty or to this style's name if this style does not have a parent style - parent = prosilver + The previously used ``style.cfg`` file has been replaced with ``composer.json`` in phpBB 4.0. The new format is more flexible and allows for better integration. 4.iii. Template Events ---------------------- -Template events must follow this format: ```` +Template events **SHALL** follow this format: ``{% EVENT event_name %}``. Using the above example, files named ``event_name.html`` located within extensions will be injected into the location of the event. +.. note:: + + The previously used ```` syntax has been deprecated in phpBB 4.0 and will be removed in a later version of phpBB. Please use the new Twig syntax instead. + Template event naming guidelines ++++++++++++++++++++++++++++++++ From 773045a973426e5a440806abecba1a88c6545438 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Fri, 6 Jun 2025 15:08:27 -0700 Subject: [PATCH 85/98] Add section for template functions --- development/development/upgrade/400.rst | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index cb6d9012..1238e9af 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -410,3 +410,30 @@ Also have a look at the `phpBB API documentation `` + + Arguments: + + - Icon type ('font' | 'png' | 'svg') + - Icon name (e.g.: 'bold') + - Icon title; optional, default: empty ``''`` + - Hide the icon title from view; optional, default: ``false`` + - Additional classes (e.g.: 'fa-fw'); optional, defaul:t ``'fas'`` + - Additional attributes for the icon, where the key is the attribute, ``{'data-ajax': 'mark_forums'}`` results in ``data-ajax="mark_forums"``; optional, default: ``{}`` + From be80d9f134db28860dfcc6bc12964e9122d9d334 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Fri, 6 Jun 2025 15:09:15 -0700 Subject: [PATCH 86/98] Add build_select function to upgrading doc --- development/development/upgrade/400.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 1238e9af..a0cebda3 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -397,6 +397,12 @@ Also have a look at the `phpBB API documentation Date: Fri, 6 Jun 2025 15:09:38 -0700 Subject: [PATCH 87/98] Minor corrections in upgrading doc --- development/development/upgrade/400.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index a0cebda3..37065cbd 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -281,7 +281,7 @@ Also have a look at the `phpBB API documentation Date: Fri, 6 Jun 2025 15:10:04 -0700 Subject: [PATCH 88/98] Add dispatch change to trigger error in upgrading doc --- development/development/upgrade/400.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 37065cbd..172640b5 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -145,6 +145,12 @@ Also have a look at the `phpBB API documentation Date: Fri, 6 Jun 2025 20:48:36 -0700 Subject: [PATCH 89/98] Typos --- development/development/upgrade/400.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 172640b5..46f44794 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -438,7 +438,7 @@ The following table lists function changes that might affect custom Style or Ext * - ``Icon()`` - Added - ``4.0.0-a1`` - - Icons may be rendered using ``{{ Icon('font', 'bold') }}`` in Twig instead of manually writing HTML like ```` + - Icons may be rendered using ``{{ Icon('font', 'bold') }}`` in Twig instead of manually writing HTML like ````. Arguments: @@ -446,6 +446,5 @@ The following table lists function changes that might affect custom Style or Ext - Icon name (e.g.: 'bold') - Icon title; optional, default: empty ``''`` - Hide the icon title from view; optional, default: ``false`` - - Additional classes (e.g.: 'fa-fw'); optional, defaul:t ``'fas'`` + - Additional classes (e.g.: 'fa-fw'); optional, default: ``'fas'`` - Additional attributes for the icon, where the key is the attribute, ``{'data-ajax': 'mark_forums'}`` results in ``data-ajax="mark_forums"``; optional, default: ``{}`` - From c3bba0156a38eb3bb306d08743009fd14ad2a2f4 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sat, 7 Jun 2025 07:06:36 -0700 Subject: [PATCH 90/98] Completely rephrase upgrade guide docs --- development/development/upgrade.rst | 10 +++---- development/development/upgrade/400.rst | 38 +++++++++++++++---------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/development/development/upgrade.rst b/development/development/upgrade.rst index 87e6bfc0..5127080d 100644 --- a/development/development/upgrade.rst +++ b/development/development/upgrade.rst @@ -2,13 +2,11 @@ Upgrade Guide ============= -This document outlines changes introduced in different versions of phpBB. These changes may require adjustments to your -existing custom PHP code or Extension code when upgrading to specific versions from a prior versions of phpBB. -It is mainly meant to be used by core and Extension developers and does not provide end user documentation for upgrading. +This guide summarizes code-level changes introduced in various phpBB versions that may require updates to your custom PHP code, extensions, or styles during an upgrade. -Unless explicitly stated otherwise, each version describes the changes compared to the previous major or minor version -that directly preceded it. For example the upgrade guide for 4.0 will describe the changes compared to 3.3 whereas an upgrade guide -for 4.1 will describe the changes compared to 4.0. +It is intended primarily for core developers, extension authors, and style creators. **It does not cover instructions for end users performing a board upgrade.** + +Unless otherwise noted, each upgrade entry documents changes relative to the immediately preceding major or minor release. Contents: diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 46f44794..3fcd1e3b 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -2,7 +2,8 @@ phpBB 3.3 to 4.0 ================ -phpBB 4.0 is a major release that contains backward compatibility breaks and also introduces some deprecations. +phpBB 4.0 is a major release that includes backward-incompatible changes and new deprecations. +This guide highlights the most important changes and resources to help extension and style developers adapt their code. .. contents:: Table of Contents :depth: 2 @@ -14,42 +15,49 @@ Basics PHP --- -The minimum required version of PHP for phpBB 4.0 is ``8.1`` with full support for versions ``8.2`` and ``8.3``. -PHP code that worked with the supported versions of phpBB 3.3 should work with phpBB 4.0 as well but might require minor adjustments.Recommendation +phpBB 4.0 requires PHP 8.1 or higher. Most PHP code compatible with phpBB 3.3 should work in phpBB 4.0 with minimal changes, +but you may need to make adjustments depending on deprecated or changed functionality. Symfony ------- -phpBB 4.0 ships with Symfony 6.4. There are quite a few changes to the standard Symfony version that came with phpBB 3.3. -The following upgrade guides provides by Symfony might help with resolving some of the issues you might encounter when upgrading -custom PHP or Extension code for phpBB 4.0: +phpBB 4.0 uses Symfony 6.4, a significant upgrade from the version bundled with phpBB 3.3. As Symfony introduced breaking +changes across versions, we recommend reviewing the following Symfony upgrade guides when updating custom code or extensions: - `Upgrade Symfony from 3.x to 4.0 `_ - `Upgrade Symfony from 4.4 to 5.0 `_ - `Upgrade Symfony from 5.x to 6.0 `_ -You can find more upgrade guides in the `Symfony Repository `_ on GitHub. +Additional guides are available in the `Symfony GitHub repository `_. Major changes ============= Ban system ---------- -The ban system has been greatly refactored for phpBB 4.0. As part of this, the following changes were introduced: +The ban system has been significantly refactored in phpBB 4.0. Key changes include: -- Added support for banning `CIDR blocks `_ -- Added support for IPv6 banning -- Removed "exclude" functionality which resulted in ambiguous settings +- `CIDR block `_ support for banning IP ranges. +- IPv6 banning is now supported. +- “Exclude” functionality has been removed due to ambiguity and inconsistent behavior. Removal of Jabber/XMPP ---------------------- -The Jabber/XMPP functionality has been removed from phpBB 4.0. This includes the Jabber/XMPP settings in the ACP and the Jabber/XMPP notification system. -Users with Jabber/XMPP accounts will no longer receive notifications via Jabber/XMPP and have instead been migrated to email notifications. -The Jabber/XMPP functionality was removed due to the lack of support for the XMPP protocol in modern browsers and the fact that it was not widely used by phpBB users. +All Jabber/XMPP features have been removed in phpBB 4.0: + +- Jabber/XMPP settings in the ACP are gone. +- XMPP-based notifications have been discontinued. +- Users who previously used Jabber/XMPP will now receive notifications via email. + +This removal was driven by lack of browser support for XMPP and limited adoption within the phpBB community. Class and function changes ========================== +Several classes and functions have been changed or removed. If your extension or code uses phpBB internals, you’ll want to: + +- Review the updated `phpBB 4.0 API documentation `_ +- Audit your code for usages of deprecated or removed methods/classes + The following table lists class and function changes that might affect custom PHP or Extension code. -Also have a look at the `phpBB API documentation `_ for further insight into the class and function API in phpBB 4.0. .. list-table:: :widths: 15 15 10 10 50 From 525a333a215b470c4b89ca5f31a88a5b9f9ef7c6 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sat, 7 Jun 2025 08:11:14 -0700 Subject: [PATCH 91/98] Add link for twig deprecations to upgrade guide --- development/development/upgrade/400.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 3fcd1e3b..cdc3f6ae 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -29,6 +29,13 @@ changes across versions, we recommend reviewing the following Symfony upgrade gu Additional guides are available in the `Symfony GitHub repository `_. +Twig +---- +phpBB 4.0 uses Twig 3.14, which introduces deprecations that may impact extension and style development. +We recommend reviewing the official Twig deprecation guide when updating your custom templates or Twig-related code: + +- `Twig 3.x Deprecated Features `_ + Major changes ============= From ccc3f56743da4fe1656d4a9edf298de9cb49f968 Mon Sep 17 00:00:00 2001 From: rxu Date: Sat, 14 Jun 2025 23:24:37 +0700 Subject: [PATCH 92/98] Add template event listener prioritizing docs. Requires https://github.com/phpbb/phpbb/pull/6770 to get merged. --- development/extensions/tutorial_events.rst | 67 ++++++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/development/extensions/tutorial_events.rst b/development/extensions/tutorial_events.rst index 9ea6a471..641a9efa 100644 --- a/development/extensions/tutorial_events.rst +++ b/development/extensions/tutorial_events.rst @@ -82,13 +82,68 @@ text ``DEMO_PAGE``. We will fix the link text in the next section. ``config.php`` file, which will force the template engine to always look for template listeners when a page is being rendered. -It's important to understand that when phpBB compiles the templates, -there is no current system for determining the priority in which template -listeners from different extensions subscribed to the same event are -compiled. In rare cases some extensions could cause a conflict, in which case -the recommendation is for the extension authors to work together on a solution for their -conflicting template listeners. +Prioritising template event listeners (optional) +--------------------------------------- + +In rare cases, some extensions could cause a conflict when template listeners +from different extensions are subscribed to the same template event. In such cases +phpBB allows to assign the priority to template event listeners, which allows +to determine the order template event listeners will be compiled. +This can be accomplished using PHP core event listener subscribed to the +``core.twig_event_tokenparser_constructor`` core event, which should use +``template_event_priority_array`` array variable to assign the template event listener priority. +``template_event_priority_array`` array has the following format: + +:: + + '_' => [ + 'event/' => , + ], + +Example: + +.. code-block:: php + + 'set_template_event_priority', + ]; + } + /** + * Assign priority to template event listener + * + * @param \phpbb\event\data $event The event object + */ + public function set_template_event_priority($event) + { + $template_event_priority_array = $event['template_event_priority_array']; + $template_event_priority_array['acme_demo'] = [ + 'event/navbar_header_quick_links_after' => $priority, + ]; + $event['template_event_priority_array'] = $template_event_priority_array; + } + } + +In this example, ``$priority`` is an integer, the value of which defaults to 0. +Setting this integer to higher values equals more importance and therefore that +template event listener will be compiled earlier than others subscribed to the same template event. +In case of equal priority values, template event listeners will be compiled in the order +they have been read from their locations. PHP Core Events & Listeners =========================== From ca4d3b7ffc5ebef03cb00d4b5bfdd889db10f33a Mon Sep 17 00:00:00 2001 From: rxu Date: Sat, 14 Jun 2025 23:46:02 +0700 Subject: [PATCH 93/98] Adjust terms. --- development/extensions/tutorial_events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/extensions/tutorial_events.rst b/development/extensions/tutorial_events.rst index 641a9efa..9ebac10c 100644 --- a/development/extensions/tutorial_events.rst +++ b/development/extensions/tutorial_events.rst @@ -96,7 +96,7 @@ This can be accomplished using PHP core event listener subscribed to the :: - '_' => [ + '_' => [ 'event/' => , ], From a30511f4707771549c0b13e17aca999bf04bc01b Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 15 Jun 2025 01:11:10 +0700 Subject: [PATCH 94/98] Address review issues. --- development/extensions/tutorial_events.rst | 47 ++++++++-------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/development/extensions/tutorial_events.rst b/development/extensions/tutorial_events.rst index 9ebac10c..a584800d 100644 --- a/development/extensions/tutorial_events.rst +++ b/development/extensions/tutorial_events.rst @@ -83,22 +83,15 @@ text ``DEMO_PAGE``. We will fix the link text in the next section. look for template listeners when a page is being rendered. Prioritising template event listeners (optional) ---------------------------------------- - -In rare cases, some extensions could cause a conflict when template listeners -from different extensions are subscribed to the same template event. In such cases -phpBB allows to assign the priority to template event listeners, which allows -to determine the order template event listeners will be compiled. -This can be accomplished using PHP core event listener subscribed to the -``core.twig_event_tokenparser_constructor`` core event, which should use -``template_event_priority_array`` array variable to assign the template event listener priority. -``template_event_priority_array`` array has the following format: +------------------------------------------------ -:: +In rare cases, conflicts may occur when multiple extensions subscribe to the same template +event using template listeners. To resolve such conflicts, phpBB allows you to control the +order in which template event listeners are compiled by assigning them priorities. - '_' => [ - 'event/' => , - ], +This is done by subscribing a PHP event listener to the +``core.twig_event_tokenparser_constructor`` event and using the +``template_event_priority_array`` variable to define listener priorities. Example: @@ -112,11 +105,7 @@ Example: class main_listener implements EventSubscriberInterface { - /** - * Assign functions defined in this class to event listeners in the core - * - * @return array - */ + // Subscribe an event listener function to the core.twig_event_tokenparser_constructor static public function getSubscribedEvents() { return [ @@ -124,26 +113,24 @@ Example: ]; } - /** - * Assign priority to template event listener - * - * @param \phpbb\event\data $event The event object - */ + // Give your extension a high priority when rendering the navbar_header_quick_links_after template event. public function set_template_event_priority($event) { $template_event_priority_array = $event['template_event_priority_array']; $template_event_priority_array['acme_demo'] = [ - 'event/navbar_header_quick_links_after' => $priority, + 'event/navbar_header_quick_links_after' => 100, ]; $event['template_event_priority_array'] = $template_event_priority_array; } } -In this example, ``$priority`` is an integer, the value of which defaults to 0. -Setting this integer to higher values equals more importance and therefore that -template event listener will be compiled earlier than others subscribed to the same template event. -In case of equal priority values, template event listeners will be compiled in the order -they have been read from their locations. +In this example, ``100`` is an integer implying the template event priority. Higher values +indicate greater importance, meaning the corresponding template event listener +will be compiled earlier than others listening to the same event. +For example, the content of template event listener which has a priority value of ``100`` +will be rendered above/before the same template event listener which has a priority value of ``99``. +If multiple listeners share the same priority value, they will be rendered in the order they were read +from their respective filesystem locations. If no priority value set, it defaults to ``0``. PHP Core Events & Listeners =========================== From b558b9347a515e3417fce58011a03dff074350bc Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 16:19:55 +0200 Subject: [PATCH 95/98] Update to respect current status of phpBB 4 --- development/language/guidelines.rst | 30 +++++++---------------- development/language/validation.rst | 37 ++++++++++++++++------------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/development/language/guidelines.rst b/development/language/guidelines.rst index 7cf65ced..ccab9c44 100644 --- a/development/language/guidelines.rst +++ b/development/language/guidelines.rst @@ -14,7 +14,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of 2) Submissions have to be complete. Partial translations are not allowed and will be automatically denied. E-mails, text files and theme-images must also be fully translated. -3) Language packs can contain three additional files (one mandatory and four optionals) that are not present in the British English language pack: ``LICENSE`` (mandatory), ``README.md`` (optional) and ``CHANGELOG.md`` (optional). You are free to write whatever you want in the ``README.md`` file and you can list the entire version history in the ``CHANGELOG.md`` file. The ``LICENSE`` file is automatically added during the upload process so you do not have to manually add the file. Its purpose is to inform the user what license is used. Language packs inherit phpBB's license of `GNU General Public License 2.0`_ and no additional or alternative licenses are allowed. All of these additional files must be placed in the ``language/{iso}/`` directory, next to the ``iso.txt`` file. Any other additional file(s) will be detected and your submission will be denied. +3) Language packs can contain three additional files (one mandatory and four optionals) that are not present in the British English language pack: ``LICENSE`` (mandatory), ``README.md`` (optional) and ``CHANGELOG.md`` (optional). You are free to write whatever you want in the ``README.md`` file and you can list the entire version history in the ``CHANGELOG.md`` file. The ``LICENSE`` file is automatically added during the upload process so you do not have to manually add the file. Its purpose is to inform the user what license is used. Language packs inherit phpBB's license of `GNU General Public License 2.0`_ and no additional or alternative licenses are allowed. All of these additional files must be placed in the ``language/{iso}/`` directory, next to the ``composer.json`` file. Any other additional file(s) will be detected and your submission will be denied. 4) Submissions must have the following files and structure: @@ -55,20 +55,6 @@ If your language pack is denied and then resubmitted, it is placed at the end of styles.php users.php email/ - short/ - bookmark.txt - newtopic_notify.txt - post_approved.txt - post_disapproved.txt - post_in_queue.txt - privmsg_notify.txt - quote.txt - report_pm.txt - report_post.txt - topic_approved.txt - topic_disapproved.txt - topic_in_queue.txt - topic_notify.txt admin_activate.txt admin_send_email.txt admin_welcome_activated.txt @@ -83,6 +69,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of group_request.txt index.htm installed.txt + mention.txt newtopic_notify.txt pm_report_closed.txt pm_report_deleted.txt @@ -96,6 +83,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of report_closed.txt report_deleted.txt report_pm.txt + report_pm_closed.txt report_post.txt test.txt topic_approved.txt @@ -104,7 +92,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of topic_notify.txt user_activate.txt user_activate_inactive.txt - user_activate_password.txt + user_forgot_password.txt user_reactivate_account.txt user_remind_inactive.txt user_resend_inactive.txt @@ -116,6 +104,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of app.php captcha_qa.php captcha_recaptcha.php + captcha_turnstile.php cli.php CHANGELOG.md (optional) common.php @@ -138,12 +127,12 @@ If your language pack is denied and then resubmitted, it is placed at the end of prosilver/ theme/ {iso}/ - index.htm (optional) + index.htm stylesheet.css -5) Submissions should follow the recommendations in the `4.0 Translation (i18n/L10n) Guidelines`_ as closely as possible, especially the `4.0 Writing style`_. +5) Submissions should follow the recommendations in the `Coding Guidelines`_ as closely as possible. -6) All PHP and text files must be encoded in UTF-8 without BOM and a new line at the end of the file. Many modern text editors use this as a default setting, but we recommend checking it in your editor's settings. We recommend you use `Notepad++`_ or `PSPad`_, both lightweight and free. +6) All PHP and text files must be encoded in UTF-8 without BOM and have new line at the end of the file. Many modern text editors use this as a default setting, but we recommend checking it in your editor's settings. We recommend you use `Notepad++`_ or `PSPad`_, both lightweight and free. 7) The translation is mostly your work and you have a right to hold a copyright on the translation and put your name or the names of those on your team in the ``composer.json`` file in the authors section. @@ -162,8 +151,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of .. _Customisations Database: https://www.phpbb.com/go/customise/language-packs/4.0 .. _Language Packs Database: https://www.phpbb.com/languages/ .. _GNU General Public License 2.0: https://opensource.org/license/gpl-2-0 -.. _4.0 Translation (i18n/L10n) Guidelines: https://area51.phpbb.com/docs/40x/coding-guidelines.html#translation -.. _4.0 Writing style: https://area51.phpbb.com/docs/40x/coding-guidelines.html#writingstyle +.. _Coding Guidelines: https://area51.phpbb.com/docs/dev/master/development/index.html .. _Notepad++: https://notepad-plus-plus.org/ .. _PSPad: http://www.pspad.com/en/ .. _officially: https://www.phpbb.com/support/intl/ diff --git a/development/language/validation.rst b/development/language/validation.rst index 166a74eb..0216cb38 100644 --- a/development/language/validation.rst +++ b/development/language/validation.rst @@ -35,8 +35,8 @@ Package ``_`` folder. The files from above should be placed in this folder. * Revision name in the `Customisation Database`_ should be left blank, contain - the phpBB package version and/or package release name (e.g. ``3.3.10`` / - ``Bertie's translation`` for 3.3.10) for more understanding. + the phpBB package version and/or package release name (e.g. ``4.0.0`` / + ``Bertie's translation`` for 4.0.0) for more understanding. Package Validation ================== @@ -48,7 +48,7 @@ Package Validation + ``language/en/`` + ``styles/prosilver/theme/en/`` -* Language packages must contain 1 additional files: +* Language packages must contain 1 additional file: + ``language/{iso}/LICENSE`` @@ -58,13 +58,13 @@ Package Validation + ``language/{iso}/README.md`` * No other additional files are allowed! -* All folders within the language-directories must contain an ``index.htm`` file (e.g. ``language/en/acp/index.htm``, ``language/en/index.htm``, ``styles/prosilver/theme/en/index.htm``, see the `Language Pack Submission Policy`_ for a complete list.). -* An exception from this rule are the the directories for the viglink-translation and the directories which belong the phpBB package (e.g. ``language/``, ``styles/``). +* The following folders within the language-directories must contain an ``index.htm`` file: ``language/en/acp/index.htm``, ``language/en/index.htm``, ``styles/prosilver/theme/en/index.htm``. +* No ``index.htm`` is need in the directories for the viglink-translation and the directories which belong the phpBB package: ``language/``, ``styles/``) File Validation =============== -* All files must be stored using ``LF`` (LineFeed / UNIX) line endings. +* All files must be saved with ``LF`` (LineFeed / UNIX) line endings. * All ``.php`` files must have a check for the ``IN_PHPBB`` constant: .. code-block:: php @@ -79,7 +79,7 @@ File Validation BOM*. * ``.php`` files must **not** produce any output. There should be no characters before ````, - but just end with a new line + but just end with an empty new line. language/{iso}/composer.json ---------------------------- @@ -93,9 +93,9 @@ The ``composer.json`` from the default language `British English` looks like thi "name": "phpbb/phpbb-language-en", "description": "phpBB Forum Software default language", "type": "phpbb-language", - "version": "4.0.0-a1-dev", + "version": "4.0.0-RC1", "homepage": "https://www.phpbb.com", - "license": "GPL-2.0", + "license": "GPL-2.0-only", "authors": [ { "name": "phpBB Limited", @@ -113,11 +113,12 @@ The ``composer.json`` from the default language `British English` looks like thi "language-iso": "en", "english-name": "British English", "local-name": "British English", - "phpbb-version": "4.0.0-a1-dev", + "phpbb-version": "4.0.0-RC1", "direction": "ltr", "user-lang": "en-gb", "plural-rule": 1, - "recaptcha-lang": "en-GB" + "recaptcha-lang": "en-GB", + "turnstile-lang": "en" } } @@ -126,11 +127,11 @@ Main block The main block of a language's ``composer.json`` file requires these six fields of information: * ``"name":`` Must start with ``phpbb/phpbb-language-`` and be followed by the language iso code e.g.: ``phpbb/phpbb-language-de`` -* ``"description":`` Must contain a short description for your translation e.g.: ``phpBB Forum Software language package Dutch (Casual Honorifics)`` +* ``"description":`` Must contain a short description for your translation e.g.: ``phpBB Forum Software language package Dutch (Casual Honorifics)``. URLs are not allowed. * ``"type":`` Must be: ``"phpbb-language",``. Do not change this! * ``"version":`` Should be the version number of the language package. This can be different than the phpBB-version it is made for. * ``"homepage":`` You may include a URL to your website, or leave this field empty using empty quotes ``""`` -* ``"license":`` Must be: ``"GPL-2.0",``. Do not change this! +* ``"license":`` Must be: ``"GPL-2.0-only",``. Do not change this! Authors ^^^^^^^ @@ -146,21 +147,22 @@ Use this section to credit the authors and maintainers of this translation. You Support ^^^^^^^ -Use this section to provide links to your websites, email, chat channels, etc. where you provide support for this translation. +Use this section to provide links to your websites, email, chat channels, etc. where you provide support for this translation. You should have at least one contact URL e.g. the support section in the Customisation Database on www.phpBB.com Extra ^^^^^ The Extra block contains information required for the translation to function correctly within a phpBB installation. Please do not omit any of these lines, and fill them out carefully. -* ``"language-iso":`` This must be your ISO code. In British English it is ``en``. This is also the same as the directory name e.g. ``language/en/``. +* ``"language-iso":`` This must be your ISO code. In British English it is ``en``. This is also the same as the directory name e.g. ``language/en/`` or ``language/de_x_sie/``. * ``"english-name":`` The English name of your language package e.g.: ``"German (Casual Honorifics)"``. (Formerly, this was the first line of ``language/{iso}/iso.txt``.) * ``"local-name":`` The local name of your language package e.g.: ``"Deutsch (Du)"``. (Formerly, this was the second line of ``language/{iso}/iso.txt``.) -* ``"phpbb-version":`` This must represent an existing phpBB release version e.g.: ``4.0.1``. Individual naming is not allowed here! +* ``"phpbb-version":`` This must represent an existing phpBB release version e.g.: ``4.0.0``. Individual naming is not allowed here! * ``"direction":`` Use ``"ltr""`` for "left-to-right" languages (e.g.: Italian, Dutch, German) and ``"rtl"`` for right-to-left language (e.g.: Arabic). -* ``"user-lang":`` Input the user language code, e.g.: "de". (Formerly defined in the ``language/{iso}/common.php`` e.g.: ``'USER_LANG' => 'de',``.) +* ``"user-lang":`` Input the user language code, e.g.: "de". (Formerly defined in the ``language/{iso}/common.php`` e.g.: ``'USER_LANG' => 'de',`` or ``'USER_LANG' => 'de-x-sie',``.) * ``"plural-rule":`` Input the plural rule number of your language. (Formerly defined in the ``language/{iso}/common.php`` e.g.: ``'PLURAL_RULE' => 1,``.) Check the `plurals`_ section for more details. * ``"recaptcha-lang":`` Input the ReCaptcha-Language-Code here. (Formerly defined in the ``language/{iso}/captcha_recaptcha.php`` e.g.: ``'RECAPTCHA_LANG' => 'de',``.) Check `Google ReCaptcha`_ for further information which code to use. +* ``"turnstile-lang":`` Input the Turnstile-Language-Code here. Check `Cloudflare Turnstile`_ for further information which code to use. .. note:: @@ -314,5 +316,6 @@ License .. _officially: https://www.phpbb.com/support/intl/ .. _Dutch language: https://www.phpbb.com/customise/db/translation/dutch_casual_honorifics/ .. _Google ReCaptcha: https://developers.google.com/recaptcha/docs/language +.. _Cloudflare Turnstile: https://developers.cloudflare.com/turnstile/reference/supported-languages/ .. _plurals: https://area51.phpbb.com/docs/dev/master/language/plurals.html .. _composer.json validation: https://getcomposer.org/doc/03-cli.md#validate From ae195e1b1fafb00c9f7630e2c5edd7f8987f65d3 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sun, 28 Sep 2025 10:49:52 +0200 Subject: [PATCH 96/98] Add punctuation and an empty to validation.rst and guidelines.rst --- development/language/guidelines.rst | 2 +- development/language/validation.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/development/language/guidelines.rst b/development/language/guidelines.rst index ccab9c44..03bfe6b7 100644 --- a/development/language/guidelines.rst +++ b/development/language/guidelines.rst @@ -132,7 +132,7 @@ If your language pack is denied and then resubmitted, it is placed at the end of 5) Submissions should follow the recommendations in the `Coding Guidelines`_ as closely as possible. -6) All PHP and text files must be encoded in UTF-8 without BOM and have new line at the end of the file. Many modern text editors use this as a default setting, but we recommend checking it in your editor's settings. We recommend you use `Notepad++`_ or `PSPad`_, both lightweight and free. +6) All PHP and text files must be encoded in UTF-8 without BOM and have an empty new line at the end of the file. Many modern text editors use this as a default setting, but we recommend checking it in your editor's settings. We recommend you use `Notepad++`_ or `PSPad`_, both lightweight and free. 7) The translation is mostly your work and you have a right to hold a copyright on the translation and put your name or the names of those on your team in the ``composer.json`` file in the authors section. diff --git a/development/language/validation.rst b/development/language/validation.rst index 0216cb38..42e50bdd 100644 --- a/development/language/validation.rst +++ b/development/language/validation.rst @@ -147,7 +147,7 @@ Use this section to credit the authors and maintainers of this translation. You Support ^^^^^^^ -Use this section to provide links to your websites, email, chat channels, etc. where you provide support for this translation. You should have at least one contact URL e.g. the support section in the Customisation Database on www.phpBB.com +Use this section to provide links to your websites, email, chat channels, etc. where you provide support for this translation. You should have at least one contact URL, e.g. the support section in the Customisation Database on www.phpBB.com. Extra ^^^^^ From 8fd896a9b120de1669eaa2a497413b7fd97fe60f Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Tue, 17 Mar 2026 07:52:22 -0700 Subject: [PATCH 97/98] Add documentation for app.php becoming index.php --- development/development/upgrade/400.rst | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index cdc3f6ae..3c8c962b 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -57,6 +57,33 @@ All Jabber/XMPP features have been removed in phpBB 4.0: This removal was driven by lack of browser support for XMPP and limited adoption within the phpBB community. +Front Controller Changes +======================== + +In phpBB 4.0, the front controller used for Symfony routing has been changed +from ``app.php`` to ``index.php``. + +In phpBB 3.3.x, routes were accessed via ``app.php``:: + + /app.php/faq + +In phpBB 4.0, routes are now accessed via ``index.php``:: + + /index.php/faq + +Direct access via ``app.php`` is no longer supported. Extensions and external +integrations must use ``index.php``. + +Extensions using phpBB routing helpers (for example, +``controller_helper::route()``) do not require changes, as URLs will be +generated correctly. + +However, any hardcoded references to ``app.php`` must be updated. This includes: + +- Template files +- PHP code constructing URLs manually +- JavaScript referencing application routes + Class and function changes ========================== Several classes and functions have been changed or removed. If your extension or code uses phpBB internals, you’ll want to: From b01200c4d97857f048eeb79c0179b8dd249f8ac6 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Tue, 17 Mar 2026 07:52:52 -0700 Subject: [PATCH 98/98] Update Symfony and PHP versions mentioned --- development/development/upgrade/400.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/development/development/upgrade/400.rst b/development/development/upgrade/400.rst index 3c8c962b..c3936efb 100644 --- a/development/development/upgrade/400.rst +++ b/development/development/upgrade/400.rst @@ -15,19 +15,20 @@ Basics PHP --- -phpBB 4.0 requires PHP 8.1 or higher. Most PHP code compatible with phpBB 3.3 should work in phpBB 4.0 with minimal changes, +phpBB 4.0 requires PHP 8.2 or higher. Most PHP code compatible with phpBB 3.3 should work in phpBB 4.0 with minimal changes, but you may need to make adjustments depending on deprecated or changed functionality. Symfony ------- -phpBB 4.0 uses Symfony 6.4, a significant upgrade from the version bundled with phpBB 3.3. As Symfony introduced breaking +phpBB 4.0 uses Symfony 7.4, a significant upgrade from the version bundled with phpBB 3.3. As Symfony introduced breaking changes across versions, we recommend reviewing the following Symfony upgrade guides when updating custom code or extensions: - `Upgrade Symfony from 3.x to 4.0 `_ - `Upgrade Symfony from 4.4 to 5.0 `_ - `Upgrade Symfony from 5.x to 6.0 `_ +- `Upgrade Symfony from 6.x to 7.0 `_ -Additional guides are available in the `Symfony GitHub repository `_. +Additional guides are available in the `Symfony GitHub repository `_. Twig ----