Askie Lin2018 06 03筆記終於整理完了!找時間來實作一下或是翻譯。
CSS
, SASS
, compass
Sass, or Syntactically Awesome StyleSheets, is an extension language for CSS. With Sass, you can write clean, sustainable CSS code and solve the common repetition and maintenance challenges present in traditional CSS.
In addition to being a valuable skill for any front-end developer, transitioning from CSS to Sass is pretty smooth due to the familiar syntax. For this reason, we will be learning the SCSS (Sassy CSS) syntax.
If you are new to HTML and CSS, we recommend you take this course first.
Sass can't be directly interpreted by your browser, so it must first be converted, or compiled, to CSS before the browser can directly understand it.
Compiling refers to converting code to lower level code so that it can be executed. By compiling SCSS to CSS, it can be interpreted by your browser and the results will appear on a webpage.
Before we dive into writing Sass, let's first learn how to compile it to CSS by typing the following command in the terminal and pressing enter:
sass main.scss main.css
The sass command above takes in two arguments:
Make sure to look closely at the extensions of each file in the command above.
The first Sass construct we will learn about is nesting.
Nesting is the process of placing selectors inside the scope of another selector:
{
and closing }
curly brackets.
.parent {
color: blue;
.child {
font-size: 12px;
}
}
In the example above .child
is the child selector and .parent is the parent selector.
The above SCSS would compile to the following, equivalent CSS:
.parent {
color: blue;
}
.parent .child {
font-size: 12px;
}
Nesting allows you to see the clear DOM relationship between two selectors while also removing the repetition observed in CSS.
In SCSS, nesting is not limited only to selectors. You can also nest common CSS properties if you append a :colon
suffix after the name of the property.
For example, the following SCSS code:
.parent {
font: {
family: Roboto, sans-serif;
size: 12px;
decoration: none;
}
}
will compile to the following CSS:
.parent {
font-family: Roboto, sans-serif;
font-size: 12px;
font-decoration: none;
}
Variables in SCSS allow you to assign an identifier of your choice to a specific value.
Why is that useful? Unlike in CSS, if you need to tweak a value, you'll only have to update it in one place and the change will be reflected in multiple rules.
In Sass, $
is used to define and reference a variable:
$translucent-white: rgba(255,255,255,0.3);
Note: It's important to stick to one naming convention for variables when you first build out your codebase. This will help you reference them easily in the future.
There are different data types you can assign to a variable in CSS.
In addition to the color data type we have seen, there are also:
In addition to color, numbers, strings, booleans, and null, Sass also has two other data types, lists and maps.
1.5em Helvetica bold;
or
Helvetica, Arial, sans-serif;
Note: You can also surround a list with parentheses and create lists made up of lists.
(key1: value1, key2: value2);
Note: In a map, the value of a key can be a list or another map.
&
選擇器|The & Selector in NestingIn the next set of exercises, you'll use new Sass concepts to fix and add styles the notecard on the right so that it flips when you hover over it!
Recall that, in CSS, a pseudo-element is used to style parts of an element, for example:
::before
or ::after
the content of an element.:hover
to set the properties of an element when the user's mouse is touching the area of the element.In Sass, the & character is used to specify exactly where a parent selector should be inserted. It also helps write psuedo classes in a much less repetitive way.
For example, the following Sass:
.notecard {
&:hover{
@include transform (rotatey(-180deg));
}
}
will compile to the following CSS:
.notecard:hover {
transform: rotatey(-180deg);
}
In addition to variables and nesting, Sass has multiple constructs that reduce repetition.
In Sass, a mixin lets you make groups of CSS declarations that you want to reuse throughout your site.
The notation for creating a mixin is as follows:
@mixin backface-visibility {
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
}
Note: Mixin names and all other Sass identifiers use hyphens and underscores interchangeably.
The following code:
.notecard {
.front, .back {
width: 100%;
height: 100%;
position: absolute;
@include backface-visibility;
}
}
is equivalent to the following CSS:
.notecard .front, .notecard .back {
width: 100%;
height: 100%;
position: absolute;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
}
Mixins also have the ability to take in a value.
An argument, or parameter, is a value passed to the mixin that will be used inside the mixin, such as $visibility in this example:
@mixin backface-visibility ($visibility) {
backface-visibility: $visibility;
-webkit-backface-visibility: $visibility;
-moz-backface-visibility: $visibility;
-ms-backface-visibility: $visibility;
-o-backface-visibility: $visibility;
}
In fact, you should only ever use a mixin if it takes an argument. We will learn more about this in a later exercise.
The syntax to pass in a value is as follows:
@include backface-visibility(hidden);
In the code above, hidden is passed in to the backface-visibility mixin, where it will be assigned as the value of its argument, $visibility.
Mixin arguments can be assigned a default value in the mixin definition by using a special notation.
A default value is assigned to the argument if no value is passed in when the mixin is included. Defining a default value for each argument is optional.
The notation is as follows:
@mixin backface-visibility($visibility: hidden) {
backface-visibility: $visibility;
-webkit-backface-visibility: $visibility;
-moz-backface-visibility: $visibility;
-ms-backface-visibility: $visibility;
-o-backface-visibility: $visibility;
}
In the example above, if no value is passed in when backface-visibility is included, hidden would be assigned to all properties.
In general, here are 5 important facts about arguments and mixins:
@include
statement.Here are some concrete examples of the rules:
@mixin dashed-border($width, $color: #FFF) {
border: {
color: $color;
width: $width;
style: dashed;
}
}
span { /* only passes non-default argument */
@include dashed-border(3px);
}
p { /* passes both arguments */
@include dashed-border(3px, green);
}
div { /* passes out of order but explicitly defined */
@include dashed-border(color: purple, width: 5px);
}
Sass allows you to pass in multiple arguments in a list or a map format.
For example, take the multiple properties needed to create the college-ruled stripes in the back of our notecard.
@mixin stripes($direction, $width-percent, $stripe-color, $stripe-background: #FFF) {
background: repeating-linear-gradient(
$direction,
$stripe-background,
$stripe-background ($width-percent - 1),
$stripe-color 1%,
$stripe-background,
$width-percent
);
}
In this scenario, it makes sense to create a map with these properties in case we ever want to update or reference them.
$college-ruled-style: (
direction: to bottom,
width-percent: 15%,
stripe-color: blue,
stripe-background: white);
When we include our mixin, we can then pass in these arguments in a map with the following ...
notation:
.definition {
width: 100%;
height: 100%;
@include stripes($college-ruled-style...);
}
Note: Remember to always prioritize readability over writing less code. This approach is only useful if you find it adds clarity to your codebase.
In Sass, string interpolation is the process of placing a variable string in the middle of two other strings.
In a mixin context, interpolation is handy when you want to make use of variables in selectors or file names. The notation is as follows:
@mixin photo-content($file) {
content: url(#{$file}.jpg); /* string interpolation */
object-fit: cover;
}
/*....*/
.photo {
@include photo-content('titanosaur');
width: 60%;
margin: 0px auto;
}
String interpolation would enable the following CSS:
.photo {
content: url(titanosaur.jpg);
width: 60%;
margin: 0px auto;
}
Sass allows & selector usage inside of mixins. The flow works much like you think it would:
&
selector gets assigned the value of the parent at the point where the mixin is included.null
and Sass will throw an error.@mixin text-hover($color){
&:hover {
color: $color;
}
}
In the above, the value of the parent selector will be assigned based on the parent at the point where it is invoked.
.word {
display: block;
text-align: center;
position: relative;
top: 40%;
@include text-hover(red);
}
The above will compile to the following CSS:
.word {
display: block;
text-align: center;
position: relative;
top: 40%;
}
.word:hover {
color: red;
}
Notice that the mixin inherited the parent selector .word because that was the parent at the point where the mixin was included.
This lesson has introduced you to some of the most powerful concepts Sass has to offer!
Functions and operations in Sass allow for computing and iterating on styles.
With Sass functions you can:
As mentioned, Sass specifically comes equipped with functions that make working with colors easier.
The alpha parameter in a color like RGBA or HSLA is a mask denoting opacity. It specifies how one color should be merged with another when the two are on top of each other.
In Sass, the function fade-out
makes a color more transparent by taking a number between 0 and 1 and decreasing opacity, or the alpha channel, by that amount:
$color: rgba(39, 39, 39, 0.5);
$amount: 0.1;
$color2: fade-out($color, $amount); /* rgba(39, 39, 39, 0.4) */
fade-in
color function changes a color by increasing its opacity:$color: rgba(55,7,56, 0.5);
$amount: 0.1;
$color2: fade-in($color, $amount); /* rgba(55,7,56, 0.6) */
-hue($color, $degrees)
changes the hue of a color by taking color and a number of degrees (usually between -360 degrees and 360 degrees), and rotate the color wheel by that amount.Sass also allows us to perform mathematical functions to compute measurements— including colors.
Here is how Sass computes colors:
$color: #010203 + #040506;
The above would compute piece-wise as follows:
01 + 04 = 05
02 + 05 = 07
03 + 06 = 09
and compile to:
color: #050709;
Sass arithmetic can also compute HSLA and string colors such as red and blue.
The Sass arithmetic operations are:
+
-
*
/
%
Note: Modulo, or %, is the remainder in a given division, so "9%2" would be "1".
SCSS arithmetic requires that the units are compatible; for example, you can't multiply pixels by ems.
Also, just like in regular math, multiplying two units together results in squared units:10px * 10px = 100px * px.
Since there is no such thing as squared units in CSS, the above would throw an error. You would need to multiply 10px * 10 in order to obtain 100px.
In CSS the /
character can be used as a separator.
In Sass, the character is also used in division.
Here are the specific instances /
counts as division:
Here are a few examples:
width: $variable/6; /* division */
line-height: (600px)/9; /* division */
margin-left: 20-10 px/ 2; /* division */
font-size: 10px/8px; /* not division */
Beyond the simple math and color transformations we explored in the previous exercises, Sass also allows for more complex functions.
Each loops in Sass iterate on each of the values on a list. The syntax is as follows:
@each $item in $list {
/* some rules and or conditions */
}
The value of $item
is dynamically assigned to the value of the object in the list according to its position and the iteration of the loop.
For loops in Sass can be used to style numerous elements or assigning properties all at once. They work like any for-loop you've seen before.
Sass's for loop syntax is as follows:
@for $i from $begin through $end {
/* some rules and or conditions */
}
In the example above:
$i
is just a variable for the index, or position of the element in the list$begin
and $end are placeholders for the start and end points of the loop.For-loops are useful for many things, but in the following exercises we will be using them to style a block of rainbow divs!
In Sass, if()
is a function that can only branch one of two ways based on a condition.
You can use it inline, to assign the value of a property:
width: if( $condition, $value-if-true, $value-if-false );
For cases with more than two outcomes, the @if, @else-if, and @else directives allow for more flexibility.
@mixin deck($suit) {
@if($suit == hearts || $suit == spades){
color: blue;
}
@else-if($suit == clovers || $suit == diamonds){
color: red;
}
@else{
/* some rule */
}
}
The mixin above is a good example for how we would want to handle the coloring of a deck of cards based on a suit condition.
There are other native Sass functions available to use, and you can even make your own custom functions if you have a good foundation in Ruby, check out more information here.
Congrats! This lesson equipped you with new knowledge on some of the most popular functions and operations available to you in SCSS. Next, let's learn about the best practices for growing your Sass codebase.
Sass can be confusing if it's not organized correctly. In this unit, we will dive into the language's best practices.
From file organization, to understanding when is best to include a mixin or extend a placeholder, we will learn about the methods that get the most out of Sass.
We'll start with best practices for organizing files. As your web app or web page grows in complexity, so will the styles that go along with it. It's best to keep code organized.
In addition to having a solid file structure, a big part of staying organized is splitting up the logic into smaller manageable components.
Sass extends the existing CSS @import
rule to allow including other SCSS and Sass files.
@import
command takes a filename to import.By default, @import
looks for a Sass file in the same or otherwise specified directory but there are a few circumstances where it will behave just like a CSS @import
rule:
@import
has any media queries.In addition to keeping code organized, importing files can also save you from repeating code. For example, if multiple SCSS files reference the same variables, importing a file with variables partial would save the trouble of redefining them each time.
Analyze the file architecture currently set up for the project by clicking on the file icon on the top left hand corner of your code editor. You will be using this to navigate between files.
The lemonade stand is a smaller project, so we have only set up a helper folder. As it grows, we could add partials for _pages, _components and more!
Partials in Sass are the files you split up to organize specific functionality in the codebase.
_
prefix notation in the file name that tells Sass to hold off on compiling the file individually and instead import it._filename.scss
For example, to import a file named _variables.scss, add the following line of code:
@import "variables";
The global file imports all the components and centralizes the logic.
Many times, when styling elements, we want the styles of one class to be applied to another in addition to its own individual styles, so the traditional approach is to give the element both classes.
<span class="lemonade"></span>
<span class="lemonade strawberry"></span>
This is a potential bug in maintainability because then both classes always have to be included in the HTML in order for the styles to be applied.
Enter Sass's @extend
. All we have to do is make our strawberry class extend .lemonade
and we will no longer have this dilemma.
.lemonade {
border: 1px yellow;
background-color: #fdd;
}
.strawberry {
@extend .lemonade;
border-color: pink;
}
If you observe CSS output, you can see how @extend
is working to apply the .lemonade
rules to .strawberry
:
.lemonade, .strawberry {
border: 1px yellow;
background-color: #fdd;
}
.strawberry {
@extend .lemonade;
border-color: pink;
}
If we think of .lemonade
as the extendee, and of .strawberry as the extender, we can then think of Sass appending the extender selector to the rule declarations in the extendee definition.
This makes it easy to maintain HTML code by removing the need to have multiple classes on an element.
Sometimes, you may create classes solely for the purpose of extending them and never actually use them inside your HTML.
Sass anticipated this and allows for a special type of selector called a placeholder, which behaves just like a class or id selector, but use the % notation instead of # or .
Placeholders prevent rules from being rendered to CSS on their own and only become active once they are extended anywhere an id or class could be extended.
a%drink {
font-size: 2em;
background-color: $lemon-yellow;
}
.lemonade {
@extend %drink;
/* more rules */
}
would translate to:
a.lemonade {
font-size: 2em;
background-color: $lemon-yellow;
}
.lemonade {
//more rules
}
Placeholders are a nice way to consolidate rules that never actually get used on their own in the HTML.
Sweet! Recall that mixins, unlike extended selectors, insert the code inside the selector's rules wherever they are included, only including "original" code if they are assigning a new value to the rule's properties via an argument.
Let's look at the @mixin
and @extend
constructs closely and compare output:
@mixin no-variable {
font-size: 12px;
color: #FFF;
opacity: .9;
}
%placeholder {
font-size: 12px;
color: #FFF;
opacity: .9;
}
span {
@extend %placeholder;
}
div {
@extend %placeholder;
}
p {
@include no-variable;
}
h1 {
@include no-variable;
}
would compile to:
span, div{
font-size: 12px;
color: #FFF;
opacity: .9;
}
p {
font-size: 12px;
color: #FFF;
opacity: .9;
/* rules specific to ps */
}
h1 {
font-size: 12px;
color: #FFF;
opacity: .9;
/* rules specific to ps */
}
We can clearly see extending results in way cleaner and more efficient output with as little repetition as possible.
As a general rule of thumb, you should:
class
, id
, or placeholder
.In addition to the directives you have learned in this course, be sure to check out the many additional available Sass functions and directives.