CSS 🐠

Cascading style sheets

CSS under the hood and best practices?

Browser

  • Loads the HTML

  • Parse the HTML

  • Create the DOM tree

  • Meanwhile, after the step2, it also loads CSS

  • Parses CSS (2 Steps)

    • Resolve conflicting CSS declarations through a process known as cascades

    • Process final CSS values (like converting % into px and so on)

    • Finally, the parsed CSS is stored in CSOM (CSS Object model just like DOM)

  • DOM + CSOM forms rendered tree

  • The browser uses the Visual formatting model to render the page using the rendered tree.

  • Finally, the website is rendered to the screen

Behined the scenes

CSS Parsing phase

Remember, in the parsing phase we have two steps: Let's look at the first step

  • Resolve conflicting CSS declarations through a process known as cascades

CSS Cascades

What is CSS Cascade

The CSS can come from many sources

  • The one we write is called Author declarations

  • The other one is User declaration where the user changes CSS in the browser

  • Browser declarations (default/ user-agent css) when no styles are applied by the developer

The cascade resolves conflicts using Specificity

CSS Architecture and BEM Methodology (Block Element Modifier)

How to architect the code

BEM is one of the CSS class naming conventions while writing HTML markups

BEM methodology
CSS Folder structure

Responsive images

Why we need responsive images

Three ways of using responsive images

Overview: High resolution means high pixels. For example, Normal resolutions use 100 physical pixels to display 100px (1X screen). High resolution will have 2 physical pixels per 1px. So 100px will actually have 200 physical pixels (2X screens - Macbook with retina display)

  • Resolution switching - Using the same image but with a lower resolution for the small screen

  • Density switching (We use srcset instead of src) - Reducing the pixel density for a low-resolution screen. Using a different image that has low pixel density for a lower resolution screen. One image for higher res and the other for lower res.

srcset in density switching
  • Art direction (we use picture) - Using a different image altogether for a smaller screen

picture and source in art-direction
Responsive images

3 pillars of a good web-design

3 pillars of good web design

Vertically aligning items in center is a night-mare. Here's how to do it.

margin: auto auto doesn't work. Second auto places in certer but first auto is considered to be 0. This is as per w3C standards but not sure why.

There are a few points you should understand before approaching this

  • Position absolute lifts up the element from normal flow and places it at the left top corner (still floated and not on the base yet) of relatively positioned element.

  • When element is still floating, the margin:auto doesn't work. The width, and height and margin(of some value) still works. The moment you set position :absolute, the width and height sets to fit content even though it is a block element.

How to remember what works

  • Well, imagine the element is lifted to outer dimension and it has no access to it's sorroundings. In that case the margin:auto cannot be set because margin is related to it's sorrounding. When I say margin 20px, this works because it understands, "Ok I need to move 20px all sides". Remember it is still not related to it's sorroundings.

  • So the question is how to remember what properties work on an absoultely positioned/lifted element? Any property which is related to element itself and not to it's sorroundings will work. Except margin:auto everything else work as they are related to the element itself.

  • Now considering back the floating element again. First, for a floated element to sit back on the normal flow, we need to specify top, bottom,left and right. Doing so will bring back the element to where ever we want.

  • This is the way we pick an element from where we don't want by defining position: absoulte and put it back where ever we want by using top, left, bottom and right.

  • Now that we understand how positioned absiolute works, we can now say the margin auto works now on absolutely positioned element after defining top,left,bottom and right.

Now that we understood the basics, lets move on.

  • To center the element vertically, the element must be positioned abosulte, set top, bottom, left and right to 0 and then put margin:auto auto.

  • But that's not it, the relative container and this absolute container should have a height defined.

  • Talking about the height, one thing is worth keeping in mind. Body height can be set to 100% only when it's parent's height (html height is set to 100%)

  • Container (div) inside body can be set (height) to 100% only when body's height is 100%. Meaning, for div to have 100% height, body and html should have 100% height. That is so much of pain. The simple way to directly set the height of this div container is by doing height:100vh. This is why 100vh is better than 100%.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./css/main.css" />
  </head>
  <body>
    <div class="container">
      <div class="center-container">
        <p>Please center me</p>
      </div>
    </div>
  </body>
</html>

How many ways CSS can be added to HTML?

3 ways

  • Inline styles ---- 1st priority

  • <style></style> tag within head ----- whichever comes first compared to link. Technically it should be placed inside the head but the truth is it can be placed anywhere in the HTML document and how many ever times you want.

  • External CSS - Linking style sheet to HTML using link tag in the head ----- whichever comes first compared to <style> tag

// Ist way

<body style="background-color: blue;">
</body>

// Second way
<style> 
 body{
  background-color: red
  }
</style>

//Third way (recommended) Linking style sheet to html
<link rel="stylesheet" href="style.css">

CSS Selectors

Before continuing, always remember, this is the way to read the style. for example,

h3 p{

Style is applied to second occuring element which is p and not h3. This rule applies to all the combinators. Let's say for div + h3, the style is applied on second occuring element which is h3 and not div (which is first occuring in the equation).

}

This is how you should read it. Apply style on p appearing in h3. Now continue to read different selectors

There 5 Major types of selectors

  1. Simple selectors (select elements based on name, id, class)

    1. Universal selector (*)

    2. Element selector (h1, p, etc)

    3. ID selector (#)

    4. Class Selector (.)

    5. Group Selector (h1,h2,h3)

    6. Small variation of 2 and 5. -> h3.myclass{ color : red} // all h3 having myclass class gets red color

  2. Combinator selectors (select elements based on a specific relationship between them)

  3. Pseudo-class selectors (select elements based on a certain state)

  4. Pseudo-elements selectors (select and style a part of an element)

  5. Attribute selectors (select elements based on an attribute or attribute value)

1. Simple selectors

/* Universal selector - Selects everything on the page */
*{
  margin:0;
  padding:0;
  box-sizing: border-box;
}

/* ********************************** */


/* Element Selector */
p {
  text-align: center;
  color: red;
}

/* ********************************** */


/* ID Selector */
#para1 {
  text-align: center;
  color: red;
}

/* Class selector */
.center {
  text-align: center;
  color: red;
}
/* ********************************** */

/* Group selectors - Selectors having same props can be grouped together */
h1 {
  text-align: center;
  color: red;
}

h2 {
  text-align: center;
  color: red;
}

p {
  text-align: center;
  color: red;
}

/* The above can be grouped as */
h1, h2, p {
  text-align: center;
  color: red;
}

/* ********************************** */

/* Some variations of the above */
/* select all the p tags having class red in it*/

p.red{
 color:'red'
}

2. Combinator selector

There are 4 combinator selectors

  • Descendant combinator (ul li) - all something inside something

  • Child combinator (div > p) - all direct children (p in this case) inside parent (div in this case)

  • Adjacent sibling combinator (h3 + p) - one p next to (sibling of) h3

  • General sibling combinator (h3 ~ p) - all p next to (siblings of ) h3

/* Descendent combinator selector */ 

/*html*/

  <ul>
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
  <li>Four</li>
 </ul>
 
 /*css*/
 
 ul li{
  color:green /* all li inside ul is targeted*/
 }
 
 /* ********************************** */
 

 /* Child combinator selector */ 
 
 /*html*/
 
 <div>
      <p>This is a paragraph at outer level</p>  //style applied
      <article>
        <p>This is a para inside article inside div</p> //not applied
      </article>
      <p>This is a paragraph at outer level</p> //style applied 
  </div>
  
  
 /*css*/
 div > p {
        color: red; /* all direct p inside div*/
     }
 
 
 /* ********************************** */
 
  /* Adjacent sibling combinator selector */ 

/*html*/

 <p>This is p next to (above) h3</p>
    <p>This is p next to (above) h3</p>
    
    <h3>This is h3</h3>
    <p>This is p next to (below - applied to this) h3</p>
    
    <p>This is p next to (below) h3</p>
    <p>This is p next to (below) h3</p>
    
    <h3>This is h3</h3>
    <p>This is p next to (below - applied to this) h3</p>
    
    <div>
      <p>This is p inside div</p>
    </div>

/*css*/

  h3 + p {
        color: green; /* applied only to the first direct p that is next to (below and not above) h3 */
      }
      
/* ********************************** */

  /* General sibling combinator selector */ 

 /*html*/
 <p>This is p next to (above) h3</p>
    <p>This is p next to (above) h3</p>
    
    
    <h3>This is h3</h3>
    <p>This is p next to (below - applied to this) h3</p>
    <p>This is p next to (below - applied to this) h3</p>
    <p>This is p next to (below - applied to this) h3</p>
    
    <h3>This is h3</h3>
    <p>This is p next to (below - applied to this) h3</p>
    
    <div>
      <p>
        This is p inside div - NOT APPLIED AS THIS IS NOT A SIBLING WHICH IS
        INSIDE div
      </p>
    </div>
 
 /*css*/
 
 h3 ~ p {
        background-color: #fff;
        color: black;
      }
      
  /*
  
  
  NOTE : One difference between + and ~. + means select only one element next 
  to the given element whereas ~ means all elements next to given element  
  
  
  */

3. Pseudo-class selector (:)

A pseudo-class is a keyword added to an element to define a special state of that element.

For example, it can be used to:

  • Style an element when a user mouses over it

  • Style visited and unvisited links differently

  • Style an element when it gets focus

Some of the most used pseudo-classes

/*hover on any element*/
a:hover{
 color:green;
}
 /* ********************************** */
/*for a link, there are different states so that can be selected*/

a:link{
 color:blue; /*link -> not yet clickd*/
}

a:hover{
 color:green; /*link -> hoverd*/
}

a:active{
 color: red; /*link -> which is currently clicked*/
}

a:visited{
 color: yellow; /*link -> clicked atleast once*/
}
 /* ********************************** */

/* Selects any <p> that is the first element
   among its siblings */
p:first-child {
  color: lime;
}

/* example of :first-child*/

/*html*/

<div>
  <p>This text is selected!</p> /* this is the element selected which is first-child*/
  <p>This text isn't selected.</p>
</div>

<div>
  <h2>This text isn't selected: it's not a `p`.</h2>
  <p>This text isn't selected.</p>
</div>

/*css*/
p:first-child {
  color: lime;
  background-color: black;
  padding: 5px;
}



/*html*/

case 1
<div>
  <li>S</li> 
  <li>A</li>
  <li>N</li>
  <li>D</li>
</div>

case 2

<div>
  <h2>This is h2</h2>
  <li>S</li> 
  <li>A</li>
  <li>N</li>
  <li>D</li>
</div>

/*css*/

li:first-child {
  color: blue;
  background: #000;
}

/*This css will change first li in case 1 but doesn't change anything in case 2
because in case 2, li is not the first-child but h2 is the first-child. So the 
first-child rule won't be applied.

 
Note: To make it work for case 2, we need to use first-of-type instead of first-child 
*/


 /* ********************************** */
/* Selects each <p>, but only if it is the */
/* only child of its parent */
p:only-child {
  background-color: lime;
}

/* example of :only-child*/

/*html*/

<div>
  <div>I am an only child.</div> /* only child*/
</div>

<div>
  <div>I am the 1st sibling.</div>
  <div>I am the 2nd sibling.</div>
  <div>I am the 3rd sibling, <div>but this is an only child.</div></div>
</div>


/*css*/

div:only-child {
  color: red;
}
 /* ********************************** */

/* Selects the second <li> element in a list */
li:nth-child(2) {
  color: lime;
}

/* Selects every fourth element
   among any group of siblings */
:nth-child(4n) {
  color: lime;
}
 /* ********************************** */
/* Selects every fourth <p> element
   among any group of siblings */
p:nth-of-type(4n) {
  color: lime;
}

/*html*/

<div>
  <div>This element isn't counted.</div>
  <p>1st paragraph.</p>
  <p class="fancy">2nd paragraph.</p>
  <div>This element isn't counted.</div>
  <p class="fancy">3rd paragraph.</p>
  <p>4th paragraph.</p>
</div>

/*css*/

/* Odd paragraphs */
p:nth-of-type(2n+1) {
  color: red;
}

/* Even paragraphs */
p:nth-of-type(2n) {
  color: blue;
}

/* First paragraph */
p:nth-of-type(1) {
  font-weight: bold;
}

/* This will match the 3rd paragraph as it will match elements which are 2n+1 AND have a class of fancy.
The second paragraph has a class of fancy but is not matched as it is not :nth-of-type(2n+1) */
p.fancy:nth-of-type(2n+1) {
  text-decoration: underline;
}

 /* ********************************** */
 
 /* Selects any element that is NOT a paragraph */
:not(p) {
  color: blue;
}


/* <p> elements that are not in the class `.fancy` */
p:not(.fancy) {
  color: green;
}

/*NOTE : :first was used for printing pages and :first-child must be used for css*/

Full list here. Go through when you're super bored 😐

All CSS selectors point downwards and not upwards. Meaning, I can select a child or multiple children or siblings(downwards) using parent. But I can not style the parent using the sibling using pure and direct CSS. For Example, I can hover the parent element and then change the color of the child, but I can't hover the child and change the color of the parent.

4. Pseudo-element selector (::)

A CSS pseudo-element is used to style specified parts of an element.

For example, it can be used to:

  • Style the first letter, or line, of an element

  • Insert content before, or after, the content of an element

There are 6 pseudo-element selectors

pseudo-element

usage

Works only for

Details

p::before

Insert something before the content of each <p> element

p::after

Insert something after the content of each <p> element

p::first-letter

works only for block elements

Selects the first letter of each <p> element

p::first-line

works only for block elements

Selects the first line of each <p> element

::marker

Selects the markers of list items

p::selection

If nothing is specified, just like ::selection, then it works for all elements

Selects the portion of an element that is selected by a user

content: is important inside before and after. Also, the box-sizing:border-box doesn't apply for pseudo-elements, so we might have to specify it deliberately.

*,
::before,
::after{
 box-sizing:border-box;
}
// PRACTICE HOVER AND SELECTORS

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Grid Practice</title>
  </head>
  <body>
    <style>
      h4:hover ~ div ul,
      h4:hover ~ ul {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    <h4>Hover me</h4>
    <p>This is p</p>
    <ul>
      <li>3rd child div's ul's li</li>
    </ul>
    <ul>
      <li>3rd child div's ul's li</li>
    </ul>
    <ul>
      <li>3rd child div's ul's li</li>
    </ul>
    <div>
      <ul>
        This is also ul
      </ul>
    </div>
  </body>
</html>

5. Attribute selector

Targets all the elements with a specific attribute. We can also specify weather to select the values of the attribute also, and if yes, we can choose exactly the way we want to target the value containing something in the attribute

1. With an attribute


    <style>
      p[attr]{
        color: red;
        background-color: antiquewhite;
      }
    </style>


    <p attr="s">This is a paragraph</p> // This gets selected coz it has attr attribute 
    <p>This is a paragraph</p>
    <p>This is a paragraph</p>

2. With a specific value

    <style>
      p[attr="s"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    <!-- the below two gets selected -->
    <p attr="s">This is a paragraph</p>
    <p attr="s">This is a paragraph</p>

    <p attr="m">This is a paragraph</p>
    
3. Contains a specific word (after space) in value of the attribute

    <style>
      p[attr~="word"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    
    <p attr="nospaceword">This contains a word</p>
    
    <!-- the below one gets selected -->
    <p attr="word">This word</p>

    <p attr="m">This is a paragraph</p>


4. Contains a specific word (anywhere and not only that has space) in the value attrubute
 
    <style>
      p[attr*="word"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>

    <!-- the below two gets selected -->
    <p attr="nospaceword">This contains a word</p>

    <p attr="word">This word</p>

    <p attr="m">This is a paragraph</p>
    
5. Starting with the value specified

    <style>
      p[attr^="word"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    
    <p attr="notstartingwithword">This contains a word</p>
    
    <!-- the below two gets selected -->
    <p attr="word">This word</p>

    <p attr="m">This is a paragraph</p>
    
    
6. Ending with the value specified

    <style>
      p[attr$="word"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    <!-- the below one gets selected -->
    <p attr="endingwithword">This contains a word</p>
    
    <p attr="wordhasnoending">This word</p>

    <p attr="m">This is a paragraph</p>
    
7. Starting with a value- at the beginning

      p[attr|="word"] {
        color: red;
        background-color: antiquewhite;
      }
    </style>
    <p attr="s-word">This contains a word</p>

    <!-- the below one gets selected -->
    <p attr="word-atstart">This word</p>

    <p attr="m">This is a paragraph</p>

Box Model

Nice tutorial for box-sizing and margin collapse

Margin collapse

Margin collapse happens when two boxes have a margin in between them in which case, the box which has a higher margin is considered and the box which has a lower margin also gets the same margin from the box which has a higher margin. The two margins will not get added up.

Display property

display:inline

  • Inline elements cannot have width, height, top, and bottom margin, padding. It can have left, and right margin and padding. Elements can sit side by side.

  • Example: span, a

display:block

  • Block elements will occupy the entire space even if the width is not 100%. Width and height can be set on this. Elements can't sit next to each other.

  • Example: div,h1-h6, p, form, header, footer,text-area.img

Note that the img is inline by default but behaves like an inline-block element as we can set width and height.

display:inline-block

  • Similar to inline. But we can set width, height, top and bottom margins, and paddings. Elements can sit next to each other.

  • Example: button, select

Flexbox

display:flex

Create an example in vscode with the code below and practice the given link.

<!-- FLEX BOX PRACTICE - https://css-tricks.com/snippets/css/a-guide-to-flexbox/ -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=\, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .box {
      width: 150px;
      height: 150px;
      font-size: 2rem;
      text-align: center;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .box1 {
      background-color: rgb(43, 226, 165);
    }
    .box2 {
      background-color: rgb(152, 192, 114);
    }
    .box3 {
      background-color: rgb(163, 114, 192);
    }
    .box4 {
      background-color: rgb(233, 109, 8);
    }
    .box5 {
      background-color: rgb(22, 24, 21);
      color: white;
    }
    .box6 {
      background-color: rgb(10, 13, 187);
      color: white;
    }
    .box7 {
      background-color: rgb(209, 20, 20);
      color: white;
    }
    .box8 {
      background-color: rgb(121, 111, 114);
      color: white;
    }
    .box9 {
      background-color: rgb(114, 192, 173);
    }
    .box10 {
      background-color: rgb(72, 219, 14);
    }
    .box11 {
      background-color: rgb(244, 248, 8);
    }
    .box12 {
      background-color: rgb(3, 2, 12);
      color: white;
    }

    .container {
      display: flex;
      /* flex-direction: column; */

      /* background-color: rgb(0, 183, 255); */
      height: 40vh;
      /* align-content: flex-start; */
      justify-content: space-evenly;
      /* align-items: ; */
    }
  </style>
  <body>
    <div class="container">
      <div class="box box1">1</div>
      <div class="box box2">2</div>
      <div class="box box3">3</div>
      <div class="box box4">4</div>
      <div class="box box5">5</div>
      <div class="box box6">6</div>
      <div class="box box7">7</div>
      <div class="box box8">8</div>
      <div class="box box9">9</div>
      <div class="box box10">10</div>
      <div class="box box11">11</div>
      <div class="box box12">12</div>
    </div>
  </body>
</html>

To learn each property quickly, here's the playlist you can refer to

flexbox playlist

Flex-basis : Equal to width when flex-direction is row and equal to height when flex-direction is column

After some research, I found this is the difference and there are not much differences

Grid

display:grid

Learn the interactive way above

How to remember and practice grid?

I've divided the tasks you can do so that you can code these tasks for quick practice.

  • Define 6 divs inside a container div

  • Make the grid active (display:grid)

  • Change one column to multiple columns (grid-template-columns)

  • Change the height of the rows (grid-template-rows)

  • Give the grid gap (grid-gap -> combination of grid-row-gap and grid-column-gap)

  • Now that you've learnt how to use rows and columns, apply fr units for the above inorder to make columns responsive (as window is expanded the columns also grows with fr)

  • write this 1fr 1fr 1fr in a simpler way using repeat

  • Do this with both columns and rows

  • Now define short-hand for grid-template-colums and rows which is grid-template:row/col

  • Now do the website layout with header, content, menu and footer

  • Define starting position of header and ending position to occupy the entire first row.

  • Represent the grid-col-start and grid-col-end by a short hand property grid-column

  • Do the same for footer

  • Instead of 1 / 3, you can also do 1 / span 2 (start from 1 and span 2). Also can do 1 / -1 to span from 1 to end

  • Make it a 12 col layout for menu and content to occupy the space in a proportion. (This is bit confusing but you get used to it😊

  • Make layouts shown below (grid-assignments 1 through 4) 😎 (I actually did it the first time, wow so great of me😎)

Grid assignments

Assignment 1

Assignment 1

Assignment 2

Assignment 2

Assignment 3

Assignment 3

Assignment 4

Assignment 4
  • Make the grid responsive in vertical way by adding height 100% to the container and set content and menu row to auto

NEW WAY OF POSITIONING ITEMS USING grid-template-area

  • Use grid-template-area property in container (parent) in order to make grid-area work in the elements.

  • Assignment below

grid-template-aera and grid-area
  • When viewed in normal screen the elements should be 6 and in mobile it should be 2 per row. So we need to vary amount of columns as per the width of the container.

  • Use minmax to consider 100px or 1fr (which ever is suitable to fit the screen)

  • Automatically create rows of a defined size. Till now we just defined the grid-template-rows manually like (100px 100px), but what if the items, when window is shrinked, fall back to 3rd row and in that case there is no defined height for the row. This can be done by grid-auto-rows.

Assignment 5

  • Make horizontal images 2 times wider

  • Do the same with vertical images

  • Do the same vertically and horizontally for some images at the same time

  • Doing the above creates gaps in the grid, get rid of them usinggrid-auto-flow property

Assignment 6

  • Write named lines for header, footer ,menu and content layout

Assignment 7

  • Play around with justify-content, justify-items, align-content and align-items.

Note :Justify content is the same as flex-box. In flex-box it takes values of flex-start | flex-end | center, and in the grid it takes start | end | center.space-between, space-around, space-evenly remains same as flexbox.

Note:

  • align-content is defined for container to align their entire content (all at once without changing its shape) in vertical access

  • justify-content is defined for container to align their entire content (all at once without changing its shape) in horizontal access

  • align-items is defined on continer to align items in vertical access (shape might change)

  • justify-items is defined on continer to justify items in horizontal access (shape might change)

  • To align the individual item, specify align-self in the item for vertical and justify self for horizontal.

  • Combine css grid and flex box

Practice grid by building this

CSS grid practice

Grid Cheat sheet

Grid cheat sheet

Text properties

text-align

text-align can be center/right/left. We can use this to align the text inside a div. We can't move the entire div itself using text-align.

margin:auto works to move the div to the center provided, the width of the div must be less than 100%.

text-decoration

can be underline, overline, line-through, and so on.

text-transform

capitalize, uppercase, lowercase

Font properties

font-size

Font size can be in px, rem, em and %. 1px is 1 unit of the number of pixels present on the screen. Giving this is not good because every screen size will show the fonts differently.

em is relative to the parent's font size. If parent is 10px and child is 3em then child gets 3 * 10px = 30px.


<style>
    .parent {
      font-size: 20px;
    }
    .child {
      font-size: 3em;
    }
</style>

<div class="parent">
      <p>This is in parent</p> <!-- 10px -->
      <div class="child">
        <p>This is in child</p> <!-- 3em which is 3 * 10px of parent = 30px -->
      </div>
</div>

rem is relative to the root's font size. The root is <html> stag. The default value of html is 16px.

html root font size

For easy calculations, we take this 16px root font size as 10px by making it 62.5% so it will be consistent on all screens.

html {
      font-size: 62.5%; 
      /*  now 1rem is not 16px but 1rem = 10px*/
      /* with this we can use rem everywhere and the calculation
      will be simpler. 3rem will now be 3*10px = 30px and not 
      3*16
      */
    }

% sets the font size in percentage. Let's say font-size of the element is 20px. If I set it to 200% then it will become 40%.

Min-width vs Max-width

In media queries, I always have confusion as to min-width and max-width applications. Here's the clarity

/*max-width*/
@media screen and (max-width: 768px) {
  /* below starts from 0 to 768px. Style applies if screen is between 0 and 768px*/
  .booklist {
    grid-template-columns: repeat(3, 1fr);
  }
}



/*min-width*/
@media screen and (min-width: 768px) {
  /* below starts from 768px. Style applies only if screen >= 768px*/
  .booklist {
    grid-template-columns: repeat(3, 1fr);
  }
}

Position

  • static (default) - same as relative but top/bottom/left/right/z-index has no effect.

  • relative - same as static but top/bottom/left/right/z-index will now work

  • fixed

  • absolute

  • sticky

An element with position: static; is not positioned in any special way; it is always positioned according to the normal flow of the page.

position: relative; An element with position: relative; is positioned relative to its normal position. Setting the top, right, bottom, and left properties of a relatively positioned element will cause it to be adjusted away from its normal position. Other content will not be adjusted to fit into any gap left by the element.

An element with position: fixed; is positioned relative to the viewport, which means it always stays in the same place even if the page is scrolled. The top, right, bottom, and left properties are used to position the element.

An element with position: absolute; is positioned relative to the nearest positioned ancestor (instead of positioned relative to the viewport, like fixed). However; if an absolute positioned element has no positioned ancestors, it uses the document body, and moves along with page scrolling.

Other definition of position:absolute

The element is removed from the flow and is relatively positioned to its first non-static ancestor. to/bottom etc works.

Note: A "positioned" element is one whose position is anything except static.

An element with position: sticky; is positioned based on the user's scroll position. A sticky element toggles between relative and fixed, depending on the scroll position. It is positioned relative until a given offset position is met in the viewport - then it "sticks" in place (like position:fixed).

p.head {
      background-color: blueviolet;
      position: sticky;
      top: 50px;
    }
    
    /* Position sticky always need to have top/bottom to work. generally we 
    set top unit so that when it reaches that particular unit from top 
    during scroll, it get's fixed. Unit then it remains relative*/

SaaS

Two versions of SaaS.

  1. SaaS -> Indeneted

  2. ScSS -> Parenthesis

Variables

CSS also has variables but saas had been introduced earlier.

/* CSS Variables*/
:root{
  --primary-color : black;
}

body{

  background-color: var(--primary-color)
}


/* SCSS Variables*/


$primary-color : black;

body{

  background-color: $primary-color;
}

We can use a map to store scss variables just like JS map.

$colors: (
  "main": black,
  "second": white,
);

body {
  background-color: map-get($colors, main);
  color: map-get($colors, second);
}

Nesting

  <body>
    <div class="main">
      <p class="main__paragraph">Please center me</p>
    </div>
  </body>
  
  
  //scss
  
  .main {
  background-color: blue;
  &__paragraph {
    color: white;
  }
}

//The above scss leads to css below
.main {
  background-color: blue;
}

.main__paragraph {
  color: white;
}

Looking above we can say & makes it possible to refer to the parent. What if I need . .main .main__paragraph{}. I mean the descendent selector? that's where we use interpolation

Interpolation

// Scss

.main {
  background-color: blue;
  #{&}__paragraph { -> interpolatation, to target full parent and then it's continuation 
    color: white;
  }
}


// css

.main {
  background-color: blue;
}

.main .main__paragraph { -> result of interpolation
  color: white;
}

File separation

We can separate the files in Saas for maintainablility. How to do that?

  • We create a partial saas files. This partial saas file will start with an underscore.

  • css file will not be created for this partial saas file, rather it will be treated as the part of main scss file which is just placed in a separeate file.

  • We then include this in the main saas file by using @import nameOfParatialFile. No need to put underscore or extension while importing

/*partial file   _resetss.scss  */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}



/* main.css*/

@import "./resets"; /* note that we don't have to use _ or .scss extension while importing*/

.main {
  background-color: blue;
  &__paragraph {
    color: white;
  }
}

Functions

$font-weights: (
  "regular": 300,
  "medium": 500,
  "bold": 700,
);

@function weight($property) {
  @return map-get($map: $font-weights, $key: $property);
}

.main {
  background-color: $primary-color;
  &__paragraph {
    color: $secondary-color;
    font-weight: weight("medium"); /* gives 500*/
  }
}

Mixins

Used when we want to avoid repeated typing.

Let's say we have some properties we always want to use in multple places. Then we can create a mixin for these commands and use them where we want. Writing a mixin will then be same as including those lines of CSS properties everywhere.

@mixin flexCenter {
  background-color: $primary-color;
  display: flex;
  justify-content: center;
  align-items: center;
}
.main {
  @include flexCenter; /*same as writing all the above lines*/
}

Mixin wih an argument

What if we want to change flex-direction in the above example. Let's say for a few cases we have to have flex-direction row and columns a few times, so we can pass an argument.

@mixin flexCenter($direction) {
  background-color: $primary-color;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: $direction;
}
.main {
  @include flexCenter(column);
}

Function vs Mixin

The difference is, a function is used to set the property of a CSS. Let's say we want font-weight like in above functions example, we called the function at the value of font-weight like below

font-weigth:function()

Whereas, mixin is used to replace the lines of code and not just a single CSS property. In the above mixin example, we are replacing 5 lines of code (reusing these lines of code).

So, function -> for single property and mixin for multiple CSS lines.

Use cases of mixins

  • Can be used to set light and dark themes.

@if is an if loop similar to normal if loop.

/*declare a mixin*/
@mixin theme($light-theme: true) {
  @if ($light-theme) {
    background-color: lighten($color: $primary-color, $amount: 100%);
    color: darken($color: $text-color, $amount: 100%);
  }
}
/*include in a class*/
.light {
  @include theme(true);
}

/*before applying mixin in html*/
body {
  background-color: $primary-color;
  color: $text-color;
}

/*include this in html*/
<body class="light">
  • Can be used to set media-queries

@content is a property which acts like a place-holder for set of values just like mixin. See the example below

/*Media query WITHOUT mixin*/ 

.main {
  @include flexCenter(column);
  &__paragraph {
    font-weight: weight(bold);
    margin: 2rem;
  }
  @media screen and (max-width: 800px) {
    color: blue;
  }
}



/* Media Query WITH mixin*/ 


$mobile: 800px;

@mixin mobile {

  @media(max-width:$mobile){
     @content;
  }
 
}



.main {
  @include flexCenter(column);
  &__paragraph {
    font-weight: weight(bold);
    margin: 2rem;
  }
  
  /*   @media screen and (max-width: 800px) { 
           color: blue;
       }
  */

  @include mobile {
    color: blue;
  }
}

Extend

Let's say you have two paragraphs and you have defined a bunch of styles for p1. Now, you want all those styles to be included in p2 but you want to make changes to one or two properties, then you can use extend. Imagine this like copying an object using spread operator {...} and then making necessary changes to the properties you want.

  &__paragraph1 {
    font-weight: weight(bold);
    margin: 2rem;
  }

  &__paragraph2 {
    @extend .main__paragraph1; /*saying - include everything from para1 and change margin to 4rem*/
    margin: 4rem;
  }

Calculations

/* In CSS */
margin: calc(20rem - 10rem);


/* In SaaS */
margin: 20rem - 10rem;



/*NOTE: Below is the CSS, we can't do this in SAAS (mixing types)*/
margin: calc(20rem - 1px); /*We can't mix types in Saas like this*/

Summary

Features of SaaS

  • Variables

  • Maps

  • Nesting

  • Interpolation

  • File seperation (Partial files)

  • Functions

  • Mixins (used for avoiding repeated typing)

  • Function vs Mixin

  • Use cases of mixin

  • Extend

  • Calculations

Last updated

Was this helpful?