CSS: Fundamental and Intermediate Styling Principles
By: Lance Watanabe
Tags: Web Design, CSS, Web Development

As a front-end developer, it is critical to master CSS. You will be dealing with it on a daily basis. One of the biggest frustrations with CSS is the lack of error codes. You cannot just copy an error code into google and find an answer. As such, I believe it is very import to have a thorough understand of CSS principles and how to organize your CSS code so it is maintainable. Below is an overview of the most common CSS properties you should know.

Reset: At the beginning of your CSS file, you should reset the box-sizing, padding, and margin by inserting the following code in *{}. This will make it easier to manage the spacing between elements.

box-sizing: border-box ==> prevents padding from increasing the size of the element

padding: 0 ==> sets all padding to 0

margin: 0 ==> sets all margin to 0

Relative Units:

%: percent of parent

em: multiple relative to parent.

rem: multiple relative to root element

vw: % relative to viewport width

vh: % of viewport height

Display:

block: The width of each element is 100% which means each element has its own line. List of elements that are block by default: https://www.w3schools.com/html/html_blocks.asp

inline: Elements will be bunched up against each other horizontally. Width and margin properties cannot be applied to inline elements.

inline-block: Elements will be squeezed together horizontally. You may apply width and margin properties.

flex: All direct children become flex items. More detail below.

grid: All direct children become grid items. More detail below.

Padding/Margin

Padding: Spacing between the element and inner elements. By default, padding increases the size of the element. Note, if you set box-sizing: border-box, padding will not increase the size of the element. When inspecting elements using chrome developer tools, padding is green.

elements. By default, padding increases the size of the element. Note, if you set box-sizing: border-box, padding will not increase the size of the element. When inspecting elements using chrome developer tools, padding is green. Margin: Spacing between the element and outer elements. Margins do not increase the size of the element. When inspecting elements using chrome developer tools, margin is orange.

elements. Margins do not increase the size of the element. When inspecting elements using chrome developer tools, margin is orange. Centering: You can center the child elements by using margin: auto auto. The first auto is for horizontal and the second is for vertical. To use margin: auto, the element must be “display: block.”

Dynamic Calculated Centering: You can ensure that your elements are dynamically centered using the calc() function.

margin: 0 16px;

width: calc(100vw - 32px);

Positioning:

position: static ==> Not affected by “top”, “bottom”, “left”, and “right” properties

position: relative ==> Enables the element to be positioned using “top”, “bottom”, “left”, and “right”.

position: absolute ==> Fixed relative to the nearest parent element that is “relative” positioned.

position: fixed ==> Fixed relative to the viewport

position: sticky; top: 0 ==> Fixed relative to the scroll position. It must be accompanied with a top property like “top:0” to determine how far from the top the element will remain when the user scrolls.

Line Spacing:

line-height: 1.6em

Float: Newer styling practices use flexbox instead of floats.

float: left ==> the element will move to the left of the parent container. If the parent element is using display: box, all of the elements will become inline (horizontal) instead of vertical. Note, there is no float: top or float: bottom

Overflow: Determines what happens when the inner elements overflow their container.

overflow: visible ==> By default, content that overflows outside of the element is displayed

overflow: hidden ==> Overflow content is hidden

overflow: auto ==> A scrollbar is added. Overflow content is hidden. The remaining content can be viewed by scrolling.

Pseudo-Classes:

:last-child ==> selects the last element among its siblings. You can use this pseudo-selector to avoid writing a whole new class for this element. Note, p:last-child will only select the <p> if the last child among its siblings is <p>.

:hover ==> styles the element when the user hovers over the element.

:focus ==> styles the element when the user selects it

::before ==> inserts content and styling before an element

::after ==> inserts content and styling after an element

z-index:

z-index is especially useful for making modals. A higher z-index, relative to another element, means that the given element (modal) will be placed in front of the other element. To apply z-index, you must also set a position (ie fixed, relative, absolute) to the element. The maximum z-index is 2147483648. All z-indices higher than this number will be reduced to 2147483648 which will result in bugs.

Invisibility:

visibility: hidden ==> The element still occupies its normal place in the DOM but the user will not see it.

display: none ==> The element is removed from the DOM and the user will not see it.

Opacity:

background-color: rgba(#, #, #, 0–1) => Use rgba in the parent element otherwise your child elements will not be able to change opacities.

Create a circular element/image:

border-radius: 50%

Pictures:

png files can have transparent backgrounds

jpg files can’t have transparent backgrounds

object-fit: cover ==> Cuts off the sides of the image, preserves the aspect ratio, and fills in the space.

Background Image: Centers the image on the x-axis and y-axis and covers the entire page.

background: url('') no-repeat center center/cover;

height: 100vh;

background-image: You can also set background images with the following which will resize the background image proportionately.

background-image: url("/yourImage.png");

background-size: contain;

width: 90%;

Flexbox: Flexbox is primarily used for 1-dimensional layouts (ie header). CSS grid is used for 2-dimensional layouts.

display: flex ==> set the display in the parent and all the children will be flex items.

default: The main axis is horizontal (row) and the cross-axis is vertical (column)

flex-direction: row ==> the elements will be positioned horizontally side-by-side

flex-direction: column ==> the elements will be positioned vertically on top of each other.

flex-shrink: 0 ==> In flexbox, if the size of all of the children elements is larger than the container, items will shrink so that they can fit inside of the container. The items will shrink according to the flex-shrink property. If you set flex-shrink to “0” the item will not shrink at all.

flex-grow: 1 ==> The item will increase in size so that the entire row or column is filled.

flex-basis: 0 ==> Sets the initial length of the element. This depends on the flex-direction.

flex: 1 0 200px ==> Shortcut for flex-grow, flex-shrink, flex-basis

To have the flex elements wrap, use the following code:

display: flex;

flexwrap: wrap;

Flavicons: Icons that appear in the tab of the webpage. The icon you display must be an .ico file. You can convert images into .ico files using: http://tools.dynamicdrive.com/favicon/

<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />

Advanced Selectors:

.classA.classB ==> If you want to select an element that has two classes you have to use this syntax.

.classA > p ==> selects all paragraphs that are direct children of classA.

.classA + p ==> selects the sibling paragraphs after classA.

a[target] ==> selects all <a> tags that have an “target” attribute

input[type=’text’] ==> selects all <input> tags that have a “type=text”

nth-child(): A pseudo-selector that matches the nth child of its parent. Attach this pseudo-selector to the element you are selecting (not the parent). Do not attach this pseudo-selector to the parent. For example, for an unordered list, attach the selector to the <li> as shown below.

li:first-child

/* first child of its parent */

li:last-child

/* selects the last child of its parent */

li:nth-child(2)

/* selects the 2nd child of its parent */

li:nth-child(3n+2)

/* selects every third child of its parent starting at the 2nd element. */

li:nth-child(odd)

/* selects all the odd children of the parent */

box-shadow:

box-shadow: 10px 10px teal;

Variables:

— myVariable: green ==>Put the variable in :root{} so your entire application has access to the variable. To access the variable, var( — myVariable).

Animations:

animation-fill-mode: forwards ==> at the end of the animation, it will remain at the end of the animation instead of going back to the start.

animation-name: yourAnimationName ==> set your animation-name to the keyframe property name

@keyframes: from {} to {} or 0% to 25% to 50% to 75% to 100%



background: white;

width: 200px;

height: 200px;

animation-name: animate1;

animation-duration: 2s;

}

@keyframes animate1 {

from {

width: 200px;

}

to {

width: 600px;

}

} .box {background: white;width: 200px;height: 200px;animation-duration: 2s;from {width: 200px;to {width: 600px;

Transitions:

transition: Creates an animation when coupled with a pseudo state or translation property. In the example below, we transition from a white background to a red background.

.box {

background: white;

transition: background, border-radius 2s ease-in-out;

/* same result*/

/* transition: all 2s ease-in-out; */

}

.box:hover {

background: red;

border-radius: 50%;

}

Transform:

transform: rotate(25deg) ==> rotate 25 degrees

transform: skew(25deg) ==> adjusts diagonally

transform: scale(2) ==> double in size

transform: translateY(100px) ==> moves element down 100px

CSS Grid: CSS grid is used for 2-dimensional layouts (rows and columns). Flexbox is primarily used for 1-dimensional layouts (ie header).

display: grid ==> set the display in the parent element and all the children will be grid items

grid-template-columns ==> width and number of columns.

grid-template-rows ==> height and number of rows.

grid-gap: 10px ==> spacing between each box will be 10px

.grid {

display: grid;

grid-template-columns: 200px 200px 200px;

/* auto will increase in size to fill the horizontal container */

/* grid-template-columns: 200px auto 200px; */

/* grid-template-columns: auto auto auto; */

/* grid-template-columns: repeat(3, auto); */

/* col1 = 1fraction, col2 = 2fractions, col3 = 4fractions */

/* grid-template-columns: 1fr 2fr 4fr; */

}

grid-column: 1 / span 3 ==> Assuming this element is a grid item, the element will span from the 1st column to the 4th column

.item:first-child {

/* the first child will take up columns 1-4 */

grid-column-start: 1;

grid-column-end: 4;

/* same as:

grid-column: 1 / span 3 */

}

grid-template-areas: Creates a grid representation of the output. In the example below, the header will occupy 3 columns in the first row. The content will occupy the first two columns in the second row and the sidebar will occupy 1 column in the second row. For each area in the grid-template-areas, you need to assign the area to a CSS code block using grid-area: yourArea

.container {

display: grid;

grid-template-areas:

"header header header"

"content content sidebar";

} .header {

grid-area: header;

} .content {

grid-area: content;

} .sidebar {

grid-area: sidebar;

}

SASS (Syntatically Awesome Stylesheets): SASS is CSS styling with additional features mentioned below. The browser cannot read SASS directly so it must be compiled to a CSS file (typically in the “dist” folder). As such, whenever you use relative paths in your .scss file, the path should be relative to the compiled CSS file instead of the .scss file. You may use a library (like node-sass) to compile the SASS file into CSS.

Variables: $yourVariable: yourProperty

Nesting:

header {

background: $dark-color;

color: $light-color;

padding: 1rem; h1 {

text-align: center;

}

}

Structuring: Use & to copy the current selector and add additional selectors to it. In the example below, since &-a is inside of .section, we are selecting .section-a

.section {

padding: 3rem;

/* .section-a */

&-a {

background: $primary-color;

}

}

Imports: Typically, you put the variables in a _variables.scss file. Then you import the variables using @import “variables” Note, the underscore tells the compiler not to compile the variables file at runtime.

Functions: Use functions to conditionally set styling.

Mixins: A mixin is a collection of styles you can reuse using the @include keyword. The main difference between a function and a mixin is that a function has to return a value.

Inheritance: In the example below, we declare a shared style of color in %btn-shared. We apply the shared styling using @extend %btn-shared. Inheritance is very similar to mixins except you cannot pass any arguments into inheritance.

Responsive Sizes and Media Queries: To test the application in various devices, click on the “iphone/tablet” icon in developer tools.

Widescreen: @media (max-width: 1201px) {}

Normal: @media (min-width: 769px) {} (max-width: 1200px) {}

Tablet: @media (min-width: 501px) {} (max-width: 768px) {}

Smart phone: @media (max-width: 500px) {}

Smart phone landscape: @media (max-height: 500px) {}

Responsive Design Practices:

Use fluid widths (i.e. max-width) as opposed to fixed widths

Use media queries to set styling for various viewports

Use rem units over px

Use a mobile-first approach

You can put the following code in the <head> of the html and the CSS will only activate if the viewport is less than 768px.

<link rel="stylesheet" href="css/mobile.css" media="screen and (max-width: 768px)" />

Bonus: You may also use javascript to manipulate CSS:

const navbar = document.getElementById("navbar");

navbar.style.background = "blue";

Bonus: The Lightbox Library will display a collection of images.

Download from: https://github.com/lokesh/lightbox2

copy the lightbox.min.css and lighbox.min.js (make sure you have jquery added as well)

copy all images into your image file

add <link> in the head to lightbox.min.css

add a <script> with a path to the lightbox.min.js

Wrap each <img> in <a> tags with a path to the image