HTML & CSS Guidelines (v1.0)
Google Doc (Contains same) - https://docs.google.com/document/d/1RqZqAQAmUhJqaMCL26iIvx9MS03MxKbby9My_Fbt1Do/edit#
JIRA Card - https://project-sunbird.atlassian.net/browse/SB-6076
Goal
- To bring consistency in code quality and standards across the Project.
- To set minimum quality standards.
- An effective tool for measurements in code reviewing.
- Make easy onboarding for newcomers.
Scope areas
- The responsive/ Mobile-first approach
- Cross-browser compatibility
- SEO & Social shareability
- Web Accessibility
- Performance
- Security
- Quality code - Coding style
- Good commenting practices
Mandatory Process
- Code Review - PR’s with HTML & CSS changes must be reviewed & approved by the concerned person.
- Code Review Parameters
- Reusable code = High
- Functional Issues = High
- Mobile-first approach = High
- Naming Conventions = High
- Code formatting = Medium
- Error Handling / Fallback for old browsers = High
- Code organized (written on correct location) = High
- Reuse code - Writing CSS code must be completely avoided. The approach should be -
- Check - Look for a solution in Ng2-semantic & Semantic UI and Sunbird CSS Library.
- Contribute - If solution not found in either of the libraries -> Try to write reusable generic class and contribute it to Sunbird CSS Library (Reusables folder).
CSS Formatting
- When using multiple selectors in one rule declaration, give each selector its own line.
- The code should be properly intended - use 1 soft tab (2 spaces).
- Put a space before the opening brace { in rule declarations.
- In properties, put a space after, but not before, the : character.
- Put closing braces } of rule declarations on a new line.
- The code inside media queries should be 1 soft tab intended.
- Declaration Order for properties - Put declarations in order to achieve consistent code. Related property declarations should be grouped together following the order:
- Positioning
- Box model
- Typographic
- Visual
- Quotation Marks
- Use single ('') rather than double ("") quotation marks for attribute selectors and property values.
- Do not use quotation marks in URI values (url()).
- Comments -
- Uses of z-index.
- Compatibility or browser-specific hacks.
- TODO - Mark todos and action items with TODO. Append action items after a colon as in TODO: action item if the code needs refactoring later.
- Prefer comments on their own line.
- Write detailed comments for code that isn't self-documenting:
Bad
.avatar{ |
Good
.avatar {
/* CSS to override ng2select CSS*/ /* Start */ .profile-image { border: 2px solid #eee; @media screen and (min-width:992px) { .profile-image { border: 2px solid #eee; } /* End */ |
CSS Naming Convention
Classes naming should be more predictable to use and hence it needs to be consistent. Naming convention to followed -
- Utility / Helper reusable classes (Typically single property classes) Name of such classes should be abbreviation of property followed by value. Eg -
- Padding 10px around all direction should be p-10. While only Padding top 10px should be pt-10. For vertical padding 10px should be py-10.
- Display flex should be d-flex
- Border radius 0 for all corner should be named as br-0 however if only top right corner radius is 0 then class should be brtr-0
- Extending Semantic UI framework components - Such classes should follow the same naming convention Semantic UI follows. Eg -
- Adding a small size modal should have modifier class small
- Adding one more color button should have classname of color. If name is multi-word then class should be camelCased. Eg - arcticBlue
CSS code organisation / SCSS Implementation (#SB-8105)
https://docs.google.com/document/d/1te1B983SdMEkN2MPh__WqhU0kaNLR3D4OAFXONcZGBo/edit
CSS Best Practices
- Specificity Problems -
- Avoid !important
- Never use IDs in CSS, ever. They have no advantage over classes (anything you can do with an ID, you can do with a class), they cannot be reused, and their specificity is way, way too high. Even an infinite number of chained classes will not trump the specificity of one ID.
- Do not nest selectors unnecessarily. If .header-nav {} will work, never use .header .header-nav {}; to do so will literally double the specificity of the selector without any benefit. ( Semantic follows this bad practice )
- Do not qualify selectors unless you have a compelling reason to do so. If .nav {} will work, do not use ul.nav {}; to do so would not only limit the places you can use the .nav class, but it also increases the specificity of the selector, again, with no real gain.
- JavaScript hooks - Avoid binding to the same class in both your CSS and JavaScript. Conflating the two often leads to, at a minimum, time wasted during refactoring when a developer must cross-reference each class they are changing, and at its worst, developers being afraid to make changes for fear of breaking functionality. We recommend creating JavaScript-specific classes to bind to, prefixed with .js-
<button class="btn btn-primary js-buy"> Request to Book </button> |
- Never @import css file. Never import css file within css file because it downgrades the performance of the site. ( Currently Semantic imports Roboto font in this way and Roboto font is not used at all on the portal hence this needs fixed. )
- No random big Z-index. Never give random or very high z-index. Check siblings z-index and +1 to it. Giving random high z-index can cause issues later after some complexity is increased.
- Horizontal & Vertical Box Centering -
Avoid doing box vertical & horizontal centering by adjusting left and top properties. Use transform: translate(-50%, -50%) to avoid rewriting media specific css.
Bad Code
.center { } |
Good Code
.center { |
- Avoid Hard Coded Height for background images or videos-
Avoid mentioning height. Try to use aspect ratios to avoid writing media queries.
Bad Code
.banner { background-size: contain; } @media screen and (min-width:768px){ .banner { } } @media screen and (min-width:992px){ .banner { } } |
Good Code
.banner { background-image: url(‘path-to-image.jpg’); background-size: contain; width: 100%; padding-top: 56.25%; } /* Ratios 16:9 = 56.25 % 4:3 Ratio = 75 % 1:1 = 100%; (Square) */ |
- Avoid Hardcoded height to any component like header, footer, card etc. Components will shrink and expand and their height will increase or decrease based on device size. Let component take their natural space. In this way you won't have to write code in several media queries.
- Use shorthand properties where possible.
Bad Code
padding-bottom: 2em; |
Good Code
padding: 0 1em 2em; |
- 0 and Units
Omit unit specification after “0” values, unless required. Do not use units after 0 values unless they are required. Eg -
flex: 0px; /* This flex-basis component requires a unit. */ |
- Avoid workaround values for width, padding and margin
- Bad Width: Eg - 93% or 86% or 49% etc
- Bad Margin & Padding: Eg - 11%, 3px etc
- Bad Negative Margin: -2px etc
Eg 1: If there are 2 elements .right with width 30px and .left with rest of the space
Bad Code
.left{ } @media screen and (min-width:768px){ .left{ } } @media screen and (min-width:992px){ .left{ } } |
Good Code
.left{ } |
In this way you can avoid writing media specific codes
Eg 2: try to avoid minor adjustment padding - margin
Bad Code
.center { } |
- Reusable generic classes
- Make better use of CSS cascading properties by creating generic reusable classes.
- Separate structure and skin. This will help in creating multiple variations of the same thing. Eg - Buttons, Modals etc.
- Responsive / Mobile First - A mobile-first approach to styling means that styles are applied first to mobile devices. Advanced styles and other overrides for larger screens are then added into the stylesheet via media queries. This approach uses min-width media queries.
- Avoid writing media queries (max-width: - - -) & (orientation: - - -).
- Do not repeat properties in media queries. Override the changing property only.
Bad Code
.box { position: relative; float: left; width: 100%; } @media screen and (min-width:768px) and (max-width:992px){ .box{ position: relative; float: left; width: 75%; } } @media screen and (min-width:992px){ .box { position: relative; float: left; width: 50%; } } @media screen and (min-width:600px) and (max-width:767px) and (orientation:landscape){ .box { position: relative; float: left; width: 50%; } } |
Good Code
.box { position: relative; float: left; width: 90%; } @media screen and (min-width:768px){ .box { } } @media screen and (min-width:992px){ .box { } } |
- Effective use of SCSS
- Use Mixins effectively for code consistency
- Use variables effectively for theming
- Use @imports & @extends for proper code organization & reusability.
- Avoid assigning any color & font-family directly. Look for variables, if not available create a variable and assign color value to it. This will help in Theming
- Theming
- RTL
- Try to make symmetrical things as much as possible for following properties -
- border
- border-radius
- padding
- margin
- box-shadow
- background-positions
- left, right for absolute or fixed elements
- Avoid writing following properties as much as you can -
- font-family
- text-align
- floats
- align-items and other flex related properties
- Multilingual
- Even multiple languages with the same direction can have some variations.
- Avoid following properties as much as you can - Font-family, font-size, font-weight, etc
- px vs em vs rem
- Nesting element with em can cause decreasing size issues due to inheriting parent properties. It can also cause issue with alignments specially horizontally with variation in the font-size.
- Vertical spacing won't increase/decrease based on font-size if rem is used. Example h1, h2 etc.
- Do not use em in padding-left & right as it will change alignment based on font-size. Use em in padding top and bottom as it should change with the font-size.
- rem and em have their strengths and weaknesses. They should be used differently, depending on the circumstances.
- Size in em if the property scales according to it’s font-size. Size everything else in rem or something else.
- Use px
- <html> / root font-size
- media queries breakpoints (Eg - min-width: 768px)
- box-shadow
- text-shadow
- border-width
- Use rem
- font-size
- Horizontal paddings and margins
- Use em
- Vertical paddings and margins
- Line-height
- Use %
- Width
- Use vh
- To meet full height design requirement according to the device
- Good read for em v/s rem - https://zellwk.com/blog/rem-vs-em/
CSS Useful References
- AirBnb Guidelines - https://github.com/airbnb/css
- Google Guidelines - https://google.github.io/styleguide/htmlcssguide.html
- CSS Tricks Guidelines - https://css-tricks.com/css-style-guides/
- Guide by @mdo - http://codeguide.co/#css
- Stylelint Rules - https://stylelint.io/user-guide/rules/
- Github Guidelines - https://styleguide.github.com/primer/principles/
- Centering - https://css-tricks.com/centering-css-complete-guide/
- Mobile First Approach - https://zellwk.com/blog/how-to-write-mobile-first-css/
- http://wtfhtmlcss.com/
- Wordpress RTL - https://codex.wordpress.org/Right_to_Left_Language_Support
- Specificity - https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
HTML Formatting
- New line each tag with proper indentation - Use a new line for every block, list, or table element, and indent every such child element.
- Quote attribute values - Use double ("") rather than single quotation marks ('') around attribute values.
- HTML Line-Wrapping -
- Break long lines.
- While there is no column limit recommendation for HTML, you may consider wrapping long lines if it significantly improves readability.
- When line-wrapping, each continuation line should be indented at least 4 additional spaces from the original line.
<!-- Progress circle Starts --> <md-progress-circular <!-- Progress circle ends--> |
HTML Common Mistakes
- DOCTYPE missing- The DOCTYPE should always be the very first line of your HTML code and it is case sensitive.
- Alt attribute missing - Relevant alt attribute to the image tag should always be added.
- Not closing Tags properly - Pair tags should be closed appropriately and single tags should be closed with /.
- Lists - Don’t use line breaks to show a list
- Don’t place Block elements within Inline elements
<!-- Wrong way --> |
- Missing script type
- Avoid Inline Styles
- Document doesn't have a valid hreflang
- Image size should not exceed the device height. - Try to use image in 16:9 aspect ratio or more to avoid scrolling to see complete image.
Must Have Meta Tags ( Including Responsiveness, SEO & Social Shareability )
<meta charset="utf-8" /> |
Web Accessibility
- Tab Index - Every link or form element or interactive element must have tabindex as per the navigation required.
- CSS Positioning won't affect your Tab Order; it would only change the Visual Order of your Elements. Tab Order corresponds to the DOM order!
- Avoid using tabindex values greater than 1. Doing so will make it difficult for people who rely on assistive technology to navigate and operate page content.
- It is not recommended to give positive values to your elements. You will end up jumping between them, and it will be confusing to manipulate between your element's tabindex attribute values. Instead, focus on writing them in a suitable DOM sequence.
- A negative value (usually tabindex="-1") means that the element should be focusable, but should not be reachable via sequential keyboard navigation. It's mostly useful to create accessible widgets with JavaScript.
- This is useful when you have off-screen content which appears on a specific event. You won't be able to focus any element with a negative tabindex using your keyboard, but you can do so by calling the focus() method.
- tabindex="0" means that the element should be focusable in sequential keyboard navigation, but its order is defined by the document's source order.
- Alt text - Every image must have relevant & contextualized alt text - https://webaim.org/techniques/alttext/
- ARIA - ARIA Landmark roles can help assistive technology users to quickly navigate to and past blocks of content in a web interface.
- Language attribute - Declaring a language attribute on the HTML element enables a screen reader to read out the text with correct pronunciation.
- Document Outline - Use semantic headings and structure
- Provide a “Skip to main content” link.
- Use unobtrusive JavaScript.
- Provide alternatives for users who do not have JavaScript enabled and for environments where JavaScript is unavailable.
- Associated label for all form controls (e.g. input, select etc.) (e.g. <label for="name">Name:</label><input id="name" type="text">)
- Make sure placeholder attributes are not being used in place of label tags.
Security
- Use rel=noopener attribute with 3rd party website links. https://developers.google.com/web/tools/lighthouse/audits/noopener