## CSS Reset CSS resets or normalizations are widely used to eliminate browser default style inconsistencies and provide a predictable starting point for your own styles. A _normalize_ stylesheet fixes inconsistencies between browsers while broadly retaining their default styles. A _reset_ stylesheet is the unclear option: removing all margins, paddings, and text styles. HTML pages styled _solely_ with a reset are no longer very legible or accessible. These days, frameworks take a hybrid approach. Tailwind CSS ships with "Preflight"— a combo of a normalize and reset stylesheet. ###### Common CSS resets and their estimated usage: - Eric Meyer's CSS: Provides a comprehensive reset of various elements' styles. An estimated 30-40% of web devs have used or are familiar with it. - Normalize.css: Aims to preserve useful default browser styles while correcting common inconsistencies. An estimated 40-50% of web devs have used or are familiar with it. - Bootstrap: A popular CSS framework, include its own CSS reset called Reboot, building upon Normalize.css and providing additional opinionated styles. An estimated 30-40% of web devs have used it directly or as part of the Bootstrap framework. [Making the case for CSS normalize and reset stylesheets in 2023](https://mattbrictson.com/blog/css-normalize-and-reset) ## Single CSS file vs. multiple CSS files The choice between using a single CSS file or multiple CSS files depends on the complexity and scale of the website. - Simple websites (e.g. blogs): An estimated 70-80% of simple websites use a single CSS file. - Complex websites (e.g. web apps): Common to use multiple CSS files to organize and modularize the styles, as well as performance enhancing lazy-loading of CSS files. An estimated 60-70% of complex websites and web apps use multiple CSS files. ## The box model Everything in CSS has a box around it, it's key to understand this in order to create more complex layouts. #### Block and inline boxes In CSS we have several types of boxes that generally fit into the categories of **block boxes** and **inline boxes**, describing elements in terms of page flow and in relation to other boxes on the page. You can change the display behavior of elements using `display: inline` and `display: block`. ###### Block Block-level elements start on a new line and occupy the full width by default, stacking vertically. Most elements in HTML are block-level elements by default: `<div>`, `<p>`, `<h1>` to `<h6>`, `<header>`, `<nav>`, `<section>`, etc. ###### Inline Inline-level elements do not start on a new line and only occupy the width necessary for their content. They flow horizontally within the text content. Additionally, padding and margin behave differently on inline elements. In general, you do not want to try to put extra padding or margin on inline elements. Inline-level elements: `<span>`, `<a>`, `<strong>`, `<img>`, `<input>`, `<label>`, etc. ###### Inline-block Inline-block elements behave like inline elements, but with block-style padding and margin. `display: inline-block` is useful to know about, but in practice, you'll likely end up reaching for flexbox more often. ###### Divs and spans `div`s and `span`s give no particular meaning to their content, unlike other elements such as `<strong>` and `<p>`. However, they're powerful because they can be "hook" elements, where we give them an `id` or `class` to style them with CSS. Another use case is grouping related elements under one parent element. Divs allow us to _divide_ the page into different blocks and apply styling to those blocks. Spans can be used to group text content and inline HTML elements for styling but should only be used when no other semantic HTML element is appropriate. #### The alternative box sizing model ``` html { box-sizing: border-box; } *, *::before, *::after { box-sizing: inherit; } ``` There is a standard and an alternate box model. By default, browsers use the standard box model. In the alternative box model, any size is the size of the visible box on the page. The content area size is that size minus the size for padding and border. No need to add the border and padding to calculate the real size of the box. | Standard CSS Box Model | Alternate CSS Box Model | | ----------------------------------------------------- | ------------------------------------------------------------------ | | ![Standard CSS box model](standard-css-box-model.png) | ![Alternate CSS box model \| 30%](alternate-css-box-model.png)<br> | The vast majority of experienced web developers use the alternative box sizing model in the their projects. For the following reasons: - Intuitive sizing: When you set the width or height of an element, the padding and border are included within those dimensions, rather than being added to them. - Consistency: By applying `box-sizing: border-box` to all elements, developers can ensure consistent sizing behavior. - Compatibility: Many popular CSS frameworks, such as Bootstrap and Foundation, use the `box-sizing: border-box` as their default box sizing model. # Flexbox vs Grid layout "Flexbox for one-dimensional, Grid for two-dimensional." or "Flexbox for content, Grid for layout." - Grid is mostly defined on the parent element. In flexbox, most of the layout happens on the children. - Grid is better at overlapping elements. - Flexbox can push things away: `margin-right: auto;` # CSS Units ###### Pixels (px) - Absolute-size for precise control over sizing and positioning. - In modern display tech, 1px does not necessarily equal one physical pixel. - Commonly used for specific dimensions such as images, icons, and borders. ###### Percentages (%) - Percentage relative to the size of the containing element. - Commonly used for responsive layouts. ###### ems (em) - An em is relative to the font size of the element. - An element with a font size of 16 would have one em equivalent to 16 pixels. - Commonly used for typography like font sizes, line heights, and margins. - The etymology of "em" has roots in traditional printing. Em was originally defined as the width of the uppercase "M". However, this is no longer relevant as the term has expanded to include a wider variety of languages and character sets. ###### rems (rem) - "root em" is relative to the font size of the root element (usually `<html>`). - For example, if the root element's font size is 16px, then 2rem == 32px. - Commonly used for consistent, scalable designs. >[!tip] em versus rem >Prefer rem for font sizing as a rule-of-thumb. >- You ensure consistent scaling, regardless of element nesting. >- Accessibility and readability: You better respect user's font size setting. >- You avoid the compounding effect, where nested elements can grow exponentially. ###### Viewport Units (vw, vh, vmin, vmax) - Viewport units are relative to the size of the visible area of the browser window. - Commonly used for creating full-screen sections. - `vh` = viewport height, `vw` = viewport width - `vmin` = smaller viewport length, either width or height. `vmax` = larger viewport length. # Fonts If you use the `font-family` property, and those fonts do not happen to be installed on the user's computer, then a fallback font will be displayed. If you have not defined a fallback, then the default HTML font will be used. It's best practice to use a long stack of fallback fonts. [Examples from Modern Font Stacks](https://modernfontstacks.com/) One popular stack is this ‘system font’ stack. ```css body { font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; } ``` If you want to use a font unavailable on a user's device, you will need to import the font from an online font library or a self-hosted font. Consider the performance and accessibility consequences of this. # Advanced Selectors There are _a lot_ of advanced selectors. These are the common useful and common. ## Combinators Combinators allow us to select elements based on relationships between selectors. There are four different CSS combinators: - **Descendent selector** (space) - Selects all elements that are descendants of the first selector. - **Child combinator** (`>`) - Selects all elements that are the children of the first selector. - **Adjacent sibling** (`+`) - Selects an element that is directly after the first selector. - **General sibling** (`~`) - Selects all elements that are next siblings of the first selector, regardless of order. ## Pseudo-Classes Pseudo-classes are used to define a special _state_ of an element and prefixed with a single colon. Pseudo-classes share the same specificity as regular classes [(0, 0, 1, 0)](https://css-tricks.com/specifics-on-css-specificity/). - `:focus` applies to an element that is currently selected by the user. - `:hover` affects anything under the user's mouse pointer. - `:active` applies to elements that are currently being clicked. - `:root` represents the root element of the DOM. - `:first-child` and `last-child` match elements that are the first or last child. - `:empty` will watch elements that have no child. - `:not(selector)` Selects every element that does not match the selector. - and more: `:only-child`, `:nth-child()` ## Pseudo-Elements Pseudo-elements let you style specific parts of an element and prefixed with a double colon. Pseudo-classes share the same specificity as regular classes [(0, 0, 1, 0)](https://css-tricks.com/specifics-on-css-specificity/). - `::marker` allows you to customize the styling of your `<li>` elements' bullets or numbers. - `::before` and `::after` adds extra elements onto the page. It's commonly used to decorate text. - `::selection` allows you to change the highlighting when a user selects text. - `::first-letter` and `::first-line` allow you to give special styling to the first letter or line of some text. ```css .myList::nth-child(5) {/* selects the 5th element with class myList */} .myList::nth-child(3n + 2) {/* selects every 3rd element, begging with the second */} .myList::nth-child(odd) { /* selects every odd element */ } ``` ## Attribute Selectors Attribute selectors allow you to target elements based on attribute presence or attribute values. - `[attribute]` selects elements with a specified attribute. - `selector[attribute]` we can optionally combine our attribute selectors with other types of selectors. - `[attribute="value"]` selects an attribute with a specific value. - `[attribute^="value"]` - `^=` Will match strings from the start. - `[attribute$="value"]` - `$=` Will match strings from the end. - `[attribute*="value"]` - `*=` The wildcard selector will match anywhere inside the string. ```css [src] { /* Target any element that has src attribute. */ } img[src] { /* Targets img elements that have a src attribute. */ } img[src="puppy.jpg"] { /* Targets img elements with a src attribute of "puppy.jpg" */ } ``` # Positioning CSS positioning controls the layout of elements on a web page. ### Static positioning - The default positioning mode is `position: static`. - No `top`, `right`, `bottom`, or `left` properties will affect statically positioned elements. - Example use: Regular document flow. ### Relative positioning - The same as static, except positioned relative to its normal position, without removing it from the document flow, based off `top`, `right`, `bottom`, `left` values. - In general, this is not really used. - Example use: Slight adjustments from an element's original position without affecting the layout of surrounding elements. ### Absolute positioning - Positioned relative to its nearest non-static positioned ancestor. - The element is removed from the normal document flow and no space is created for the element in the page layout. It moves as your scroll the page. - Example use: Overlaying one element above another, such as a dropdown menu. >[!warning] Prefer to use flexbox or grid >Absolute positioning has specific use cases and if possible, using flexbox or grid should be prioritized. Absolute positioning shouldn't be used to do entire page layouts. ### Fixed positioning - Positioned relative to the viewport, staying put even as the page scrolls. - Like absolute positioning, does not leave space in the document flow. - Example use: Navigation bars or chat buttons that always stay visible on screen, regardless of scroll position. ### Sticky positioning - A hybrid of relative and fixed positioning. The element is treated as relatively positioned until it cross a specified threshold, at which point it becomes fixed. - It needs a threshold set by `top`, `right`, `bottom`, or `left` to determine when to stick. - Example use: Headers that remain at the top of viewport until you scroll to a certain point. ### How to choose a CSS positioning 1. If element should move from its normal position without affecting layout, use `relative`. 2. If it needs to be removed from the flow and positioned precisely in the context of another element, choose `absolute`. 3. For elements that must remain visible, use `fixed`. 4. If the element should switch between static and fixed based on scroll position, go with `sticky`. # CSS Variables / Custom Properties - CSS variables allow us to define and reference a value many times throughout a file. - CSS variables are scoped to the selector their defined in and any of the selector's descendants. Use the `:root` selector to define globally variables. - To use a variable, use the `var()` function. The `var()` function can accept up to two parameters, where the second param is a fallback value. ```css :root { --global-color: red; } .example { --color-text: white; /* Using a locally scoped variable */ color: var(--color-text); /* Falling back to a fallback value */ background-color: var(--undeclared-property, var(--global-color)); /* Nested fallback value */ text-shadow: var(--undeclared-again, var(--shadow-color, green)); } .another-scope { /* Will only work if .example is descendant of .another-scope element */ --shadow-color: pink; } ``` ### Setting theme using `prefers-color-scheme` media query You can toggle the theme for your site by using the `prefers-color-scheme` media query, which checks what a user has selected as a theme preference on their OS/user agent. ```css :root { /* Default values in case user doesn't have preference set */ --color-base-bg: white; --theme-name: "light"; } /* Media query for user preference. Only `dark` & `light` are valid. */ @media (prefers-color-scheme: dark) { :root { --color-base-bg: black; --theme-name: "dark"; } } body { background-color: var(--color-base-bg); } .theme-name::after { content: var(--theme-name); } ``` # Supporting the Safe Area (iPhone "notch") Content can be cut off in iPhone Safari browsers if you don't consider the "notch" aka safe area. [Webkit discussed it here](https://webkit.org/blog/7929/designing-websites-for-iphone-x/). #### Meta tag: `viewport-fit=cover` Ensure you have the correct viewport meta tag. viewport-fit has three potential: - `auto` (default) - `contain`: Viewport should fully contain web content. - `cover`: Web content should fully cover the viewport. Fixed elements may be obscured. ```html <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> ``` #### Using Safe Area in CSS Apply padding or margins using these variables: ```css body { padding-top: env(safe-area-inset-top); padding-right: env(safe-area-inset-right); padding-bottom: env(safe-area-inset-bottom); padding-left: env(safe-area-inset-left } ``` ##### Handling Landscape Mode Be especially mindful of landscape orientation, where the notch is on the side: ```css @media screen and (orientation: landscape) { .sidebar { padding-right: env(safe-area-inset-right); } } ``` ##### Fixed Position Elements For fixed position headers or footers: ```css .footer { position: fixed; bottom: 0; padding-bottom: env(safe-area-inset-bottom); } ``` # Frameworks and Preprocessors CSS frameworks and preprocessors are commonly found in the workplace. ### Frameworks CSS frameworks are pre-designed libraries that provide a set of ready-to-use CSS styles and components. They speed up development time and promote consistency. Frameworks often contain a responsive grid system, pre-defined typography, styled form elements, navigation components (menus, tabs, etc.), and classes for controlling visibility and alignment. _Too many new developers jump into learning CSS frameworks too early. So, many do not get enough vanilla CSS practice under their belts to solidify the fundamentals._ - Bootstrap: Does a lot of the heavy lifting of packaging up commonly used CSS code for you, even icons and interactions (like menu dropdowns). - Tailwind: A utility-first framework that aims to change how we apply CSS through a different syntax. - Foundation: A flexible and customizable framework with a focus on semantic markup and mobile-first design. > [!NOTE] CSS frameworks: Just a bundle of CSS >Ultimately, a CSS framework is just a collection of stylesheets that you can access using the defined classes. For example, many frameworks provide a class called `.btn` that will add all the needed styles to your buttons. ### Preprocessors (aka precompilers) Preprocessors, aka precompilers, are scripting languages that extend the capabilities of traditional CSS. They introduce features like variables, mixins, nesting, and functions. Preprocessors are used to enhance the functionality and expressiveness of CSS, helping you write CSS more easily. Many of the features offered by preprocessors have since been implemented by vanilla CSS, making them less useful. For example, custom properties and nesting. - Sass (Syntactically Awesome Style Sheets): The most widely used preprocessor, known for its rich feature set and extensive community. - Less (Leaner Style Sheets): Extends CSS with dynamic behavior, offering a JS-like syntax. - Stylus: Flexibly and expressively supports both an indented syntax and standard CSS syntax.