├── src
├── scss
│ ├── layout
│ │ ├── _grid.scss
│ │ ├── _sidebar.scss
│ │ ├── _index.scss
│ │ └── _main.scss
│ ├── components
│ │ ├── _card.scss
│ │ ├── _index.scss
│ │ ├── _alert.scss
│ │ ├── _badges.scss
│ │ └── _button.scss
│ ├── utils
│ │ ├── _functions.scss
│ │ ├── _placeholders.scss
│ │ ├── _variables.scss
│ │ ├── _index.scss
│ │ └── _mixins.scss
│ ├── base
│ │ ├── _index.scss
│ │ ├── _fonts.scss
│ │ ├── _base.scss
│ │ └── _reset.scss
│ ├── --examples--
│ │ ├── lesson-05
│ │ │ ├── _btn-scema.scss
│ │ │ ├── _base.scss
│ │ │ ├── _scopes.scss
│ │ │ ├── _button.scss
│ │ │ └── _variables.scss
│ │ ├── lesson-06
│ │ │ ├── _nesting.scss
│ │ │ ├── _ampersand.scss
│ │ │ └── _combinators.scss
│ │ ├── lesson-14
│ │ │ ├── _map.scss
│ │ │ ├── _alerts.scss
│ │ │ └── _colors.scss
│ │ ├── lesson-07
│ │ │ ├── example.css
│ │ │ ├── _badge.scss
│ │ │ ├── _math.scss
│ │ │ └── _task.scss
│ │ ├── lesson-12
│ │ │ ├── _examples.scss
│ │ │ ├── _functions.scss
│ │ │ ├── _mixins.scss
│ │ │ └── _decimal.scss
│ │ ├── lesson-11
│ │ │ ├── _each.scss
│ │ │ ├── _for.scss
│ │ │ └── _if.scss
│ │ ├── lesson-13
│ │ │ └── _list.scss
│ │ ├── lesson-09
│ │ │ └── _extend.scss
│ │ └── lesson-10
│ │ │ └── _mixins.scss
│ └── main.scss
├── js
│ └── main.js
├── img
│ ├── logo-sass.png
│ ├── webp
│ │ ├── logo-sass.webp
│ │ └── employee-1.webp
│ ├── badges
│ │ └── employee-1.png
│ ├── icons
│ │ ├── github.svg
│ │ ├── gem.svg
│ │ ├── info.svg
│ │ ├── close.svg
│ │ ├── check.svg
│ │ ├── warning.svg
│ │ └── danger.svg
│ └── icons.svg
└── fonts
│ ├── Montserrat-Bold.woff2
│ └── Montserrat-Regular.woff2
├── demo
├── main-page.jpg
├── deploy-status.png
├── how-it-works.png
├── repo-settings.png
├── template-step-1.png
├── template-step-2.png
├── gh-actions-perm-1.png
├── gh-actions-perm-2.png
└── project-structure.md
├── postcss.config.cjs
├── .gitignore
├── index.html
├── package.json
├── LICENSE
├── vite.config.js
├── README.md
└── public
└── sass.svg
/src/scss/layout/_grid.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/components/_card.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/layout/_sidebar.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/utils/_functions.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/utils/_placeholders.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/utils/_variables.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/js/main.js:
--------------------------------------------------------------------------------
1 | import "../scss/main.scss";
2 |
--------------------------------------------------------------------------------
/src/scss/base/_index.scss:
--------------------------------------------------------------------------------
1 | @forward "fonts";
2 | @forward "base";
3 | @forward "reset";
4 |
--------------------------------------------------------------------------------
/src/scss/layout/_index.scss:
--------------------------------------------------------------------------------
1 | @forward "main";
2 | @forward "grid";
3 | @forward "sidebar";
4 |
--------------------------------------------------------------------------------
/demo/main-page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/main-page.jpg
--------------------------------------------------------------------------------
/demo/deploy-status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/deploy-status.png
--------------------------------------------------------------------------------
/demo/how-it-works.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/how-it-works.png
--------------------------------------------------------------------------------
/demo/repo-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/repo-settings.png
--------------------------------------------------------------------------------
/src/img/logo-sass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/img/logo-sass.png
--------------------------------------------------------------------------------
/demo/template-step-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/template-step-1.png
--------------------------------------------------------------------------------
/demo/template-step-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/template-step-2.png
--------------------------------------------------------------------------------
/demo/gh-actions-perm-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/gh-actions-perm-1.png
--------------------------------------------------------------------------------
/demo/gh-actions-perm-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/demo/gh-actions-perm-2.png
--------------------------------------------------------------------------------
/src/img/webp/logo-sass.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/img/webp/logo-sass.webp
--------------------------------------------------------------------------------
/src/img/badges/employee-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/img/badges/employee-1.png
--------------------------------------------------------------------------------
/src/img/webp/employee-1.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/img/webp/employee-1.webp
--------------------------------------------------------------------------------
/src/fonts/Montserrat-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/fonts/Montserrat-Bold.woff2
--------------------------------------------------------------------------------
/src/fonts/Montserrat-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goitacademy/sass-course-code/HEAD/src/fonts/Montserrat-Regular.woff2
--------------------------------------------------------------------------------
/src/scss/components/_index.scss:
--------------------------------------------------------------------------------
1 | @forward "button";
2 | // @forward "alert";
3 | // @forward "badges";
4 | // @forward "card";
5 |
--------------------------------------------------------------------------------
/src/scss/utils/_index.scss:
--------------------------------------------------------------------------------
1 | @forward "variables";
2 | // @forward "mixins";
3 | // @forward "functions";
4 | // @forward "placeholders";
5 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-05/_btn-scema.scss:
--------------------------------------------------------------------------------
1 | $font-size: 16px !default;
2 | $btn-color: white !default;
3 | $btn-bgcolor: hotpink !default;
4 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-05/_base.scss:
--------------------------------------------------------------------------------
1 | body {
2 | min-width: 100vw;
3 | min-height: 100vh;
4 |
5 | display: flex;
6 | justify-content: center;
7 | align-items: center;
8 | }
9 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-06/_nesting.scss:
--------------------------------------------------------------------------------
1 | .section {
2 | width: 100%;
3 |
4 | .title {
5 | color: teal;
6 | }
7 |
8 | .text {
9 | font-size: 14px;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require("postcss-sort-media-queries")({
4 | sort: "mobile-first", // default value
5 | }),
6 | // require("autoprefixer"),
7 | ],
8 | };
9 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-14/_map.scss:
--------------------------------------------------------------------------------
1 | @use "./colors" as c;
2 |
3 | /*
4 | Перевикористовуємо мапу кольорів
5 | для стилізації кнопки
6 | */
7 | .button {
8 | color: c.get-color("primary");
9 | background-color: c.get-color("background");
10 | }
11 |
--------------------------------------------------------------------------------
/src/scss/utils/_mixins.scss:
--------------------------------------------------------------------------------
1 | @use "sass:map";
2 |
3 | @mixin viewport-md {
4 | @media (min-width: 767px) {
5 | @content;
6 | }
7 | }
8 |
9 | @mixin text-gradient {
10 | background: var(--hero-name-background);
11 | background-clip: text;
12 | color: transparent;
13 | }
14 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-05/_scopes.scss:
--------------------------------------------------------------------------------
1 | $color-primary: teal; // global scope
2 |
3 | body {
4 | $color-primary: lightblue; // local scope
5 | $color-secondary: white !global;
6 | background-color: $color-primary;
7 | }
8 |
9 | p {
10 | color: $color-secondary; // undefined
11 | background-color: $color-primary;
12 | }
13 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-14/_alerts.scss:
--------------------------------------------------------------------------------
1 | $types: (
2 | "primary": #f07f2e,
3 | "success": #82c43c,
4 | "danger": #fc5a5a,
5 | "warning": #a461d8,
6 | "info": #4e75ff,
7 | );
8 |
9 | /* Генеруємо набір класів повідомлень */
10 | @each $key, $value in $types {
11 | .alert-#{$key} {
12 | background-color: $value;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-05/_button.scss:
--------------------------------------------------------------------------------
1 | @use "sass:math";
2 | @use "btn-scema" as vars with (
3 | $font-size: 10px,
4 | $btn-color: black,
5 | $btn-bgcolor: lightblue
6 | );
7 |
8 | .small-btn {
9 | font-size: vars.$font-size;
10 | color: vars.$btn-color;
11 | background-color: vars.$btn-bgcolor;
12 | }
13 |
14 | @debug math.$pi;
15 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-07/example.css:
--------------------------------------------------------------------------------
1 | /*|============================
2 | | Створити класи для бейджів
3 | |============================
4 | */
5 |
6 | .badge-completed {
7 | background-color: #a461d8;
8 | }
9 |
10 | .badge-ended {
11 | background-color: #fc5a5a;
12 | }
13 |
14 | .badge-active {
15 | background-color: #82c43c;
16 | }
17 |
--------------------------------------------------------------------------------
/src/scss/base/_fonts.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Montserrat";
3 | src: url("../fonts/Montserrat-Regular.woff2") format('woff2');
4 | font-weight: 400;
5 | font-display: swap;
6 | }
7 |
8 | @font-face {
9 | font-family: "Montserrat";
10 | src: url("../fonts/Montserrat-Bold.woff2") format('woff2');
11 | font-weight: 700;
12 | font-display: swap;
13 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-12/_examples.scss:
--------------------------------------------------------------------------------
1 | @use "mixins" as m;
2 | @use "functions" as f;
3 |
4 | .title {
5 | // font-size: 20px;
6 | // font-style: normal;
7 | // font-weight: 600;
8 | // line-height: 28px; /* 140% */
9 | // letter-spacing: 0.5px;
10 | // text-align: center;
11 |
12 | @include m.fonts(20px, 600, 28px, 0.5px, center);
13 | }
14 |
15 | .container {
16 | // width: 1000px;
17 | width: f.rem(1000px);
18 | }
19 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-11/_each.scss:
--------------------------------------------------------------------------------
1 | // @each at-rule with list
2 | $sizes: 8, 16, 20;
3 |
4 | @each $size in $sizes {
5 | .p-#{$size} {
6 | padding: #{$size}px;
7 | }
8 | }
9 |
10 | // @each at-rule with map
11 | $spacers: (
12 | "sm": 24,
13 | "md": 32,
14 | "lg": 36,
15 | "xl": 68,
16 | );
17 |
18 | @each $key, $value in $spacers {
19 | .margin-#{$key} {
20 | margin: #{$value}px;
21 | }
22 | }
23 |
24 | // next code
25 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-05/_variables.scss:
--------------------------------------------------------------------------------
1 | // $color-primary-text: #888; // kebeb case
2 | // $color-blue-text: lightblue; // kebeb case
3 |
4 | // $colorPrimaryText: #888; // camel case
5 | // $colorBlueText: lightblue; // camel case
6 |
7 | // $color_primary_text: #888; // snake case
8 | // $color_blue_text: lightblue; // snake case
9 |
10 | $font-size: 16px;
11 |
12 | .title {
13 | font-size: $font-size;
14 | }
15 |
16 | $font-size: 10px;
17 |
18 | .subtitle {
19 | font-size: $font-size;
20 | }
21 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-12/_functions.scss:
--------------------------------------------------------------------------------
1 | // Function statement
2 | @use "sass:math";
3 |
4 | @function strip-unit($value) {
5 | @if type-of($value) != "number" {
6 | @error "#{$value} is not a number.";
7 | }
8 |
9 | @if type-of($value) == "number" and not unitless($value) {
10 | @return math.div($value, ($value * 0 + 1));
11 | }
12 |
13 | @return $value;
14 | }
15 |
16 | @function rem($px-value, $base-font-size: 16px) {
17 | @return #{math.div(strip-unit($px-value), strip-unit($base-font-size))}rem;
18 | }
19 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-11/_for.scss:
--------------------------------------------------------------------------------
1 | // @for at-rule with calculations
2 | $base-weight: 400;
3 |
4 | @for $i from 0 through 3 {
5 | // 1 step: $i = 0
6 | // 2 step: $i = 1
7 | // 3 step: $i = 2
8 | // 4 step: $i = 3
9 |
10 | .fw-#{$base-weight+($i * 100)} {
11 | font-weight: $base-weight + ($i * 100);
12 | }
13 | }
14 |
15 | // difference between "through" and "to"
16 | // @for $i from 0 to 3 {
17 | // @debug "with to #{$i}";
18 | // }
19 |
20 | @for $_ from 0 through 3 {
21 | @debug $_;
22 | }
23 |
24 | $n: 0;
25 |
26 | @while $n < 4 {
27 | $n: $n + 1;
28 | }
29 |
--------------------------------------------------------------------------------
/src/scss/components/_alert.scss:
--------------------------------------------------------------------------------
1 | // Extending selectors
2 | // .notification {
3 | // border-radius: 10px;
4 |
5 | // > .icon {
6 | // display: block;
7 | // }
8 | // }
9 | div:not(:last-child) {
10 | margin: 0 auto;
11 | margin-bottom: 24px;
12 | }
13 |
14 | .notification-icon,
15 | .notification-btn-icon {
16 | fill: currentColor;
17 | }
18 |
19 | .notification-text {
20 | margin: 0;
21 | flex-grow: 1;
22 | }
23 | .notification-btn {
24 | font-family: inherit;
25 | color: currentColor;
26 | background-color: transparent;
27 | border: none;
28 | cursor: pointer;
29 | }
30 |
--------------------------------------------------------------------------------
/src/scss/components/_badges.scss:
--------------------------------------------------------------------------------
1 | @use "../base/fonts";
2 |
3 | .badges {
4 | display: flex;
5 | flex-flow: wrap;
6 | justify-content: center;
7 | align-items: center;
8 | gap: 2rem;
9 |
10 | &-item {
11 | }
12 |
13 | &-link {
14 | display: block;
15 | border-radius: 5rem;
16 | color: var(--main-text-color);
17 | text-decoration: none;
18 | background: var(--brand-color);
19 | padding: 0.8rem 1.8rem;
20 | transition: 0.2s ease;
21 |
22 | &:hover {
23 | background: var(--brand-light-color);
24 | }
25 | }
26 | }
27 | .no-link {
28 | pointer-events: none;
29 | }
30 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Lesson 12
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-06/_ampersand.scss:
--------------------------------------------------------------------------------
1 | // .link {
2 | // color: black;
3 |
4 | // &:hover,
5 | // &:focus {
6 | // color: red;
7 | // }
8 | // }
9 |
10 | .button {
11 | background: teal {
12 | position: center;
13 | repeat: no-repeat;
14 | }
15 |
16 | // color: red;
17 |
18 | &:hover,
19 | &:focus {
20 | color: blue;
21 | }
22 | }
23 |
24 | .button-icon {
25 | width: 20px;
26 | height: 20px;
27 |
28 | &:hover {
29 | width: 50px;
30 | height: 50px;
31 | }
32 |
33 | .button:hover & {
34 | font-size: 20px;
35 | }
36 | }
37 |
38 | .button-label {
39 | font-size: 16px;
40 |
41 | .button:hover & {
42 | font-size: 20px;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "starter-kit",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build --base=/starter-kit/",
9 | "preview": "vite preview",
10 | "watch": "npx vite build --watch"
11 | },
12 | "browserslist": [
13 | "cover 99.5%"
14 | ],
15 | "devDependencies": {
16 | "autoprefixer": "^10.4.4",
17 | "fast-glob": "^3.3.1",
18 | "imagemin": "^8.0.1",
19 | "imagemin-webp": "^8.0.0",
20 | "postcss-sort-media-queries": "^5.2.0",
21 | "sass": "^1.68.0",
22 | "sharp": "^0.32.6",
23 | "svgo": "^3.0.2",
24 | "vite": "^4.4.5",
25 | "vite-plugin-image-optimizer": "^1.1.7"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/scss/components/_button.scss:
--------------------------------------------------------------------------------
1 | %btn {
2 | font-family: Montserrat;
3 | font-size: 14px;
4 | font-weight: 500;
5 | line-height: 20px; /* 142.857% */
6 | letter-spacing: 0.5px;
7 | color: #fafafb;
8 |
9 | background-color: #f07f2e;
10 | border: none;
11 | cursor: pointer;
12 | transition: 300ms;
13 |
14 | &:hover {
15 | background-color: #f15c27;
16 | box-shadow: 0px 4px 10px 0px rgba(240, 127, 46, 0.25);
17 | }
18 | }
19 |
20 | .btn-sm {
21 | @extend %btn;
22 |
23 | display: inline-flex;
24 | padding: 4px 8px;
25 | }
26 | .btn-md {
27 | @extend %btn;
28 |
29 | display: inline-flex;
30 | padding: 8px 12px;
31 | }
32 | .btn-lg {
33 | @extend %btn;
34 |
35 | display: inline-flex;
36 | padding: 16px 20px;
37 | }
38 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-07/_badge.scss:
--------------------------------------------------------------------------------
1 | .badge-info {
2 | color: #b5b5be;
3 | font-size: 14px;
4 | line-height: 20px; /* 142.857% */
5 | letter-spacing: 0.5px;
6 | text-align: right;
7 | }
8 | .badge {
9 | min-width: 96px;
10 | padding: 4px 8px;
11 |
12 | color: #fff;
13 | text-align: center;
14 | font-size: 14px;
15 | font-style: normal;
16 | font-weight: 500;
17 | line-height: 20px; /* 142.857% */
18 | letter-spacing: 0.07px;
19 |
20 | border-radius: 20px;
21 | background-color: #92929d;
22 | }
23 |
24 | // Practice
25 | $status: (
26 | "completed": #a461d8,
27 | "ended": #fc5a5a,
28 | "active": #82c43c,
29 | );
30 |
31 | @each $status-text, $color in $status {
32 | .badge-#{$status-text} {
33 | background-color: $color;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-07/_math.scss:
--------------------------------------------------------------------------------
1 | /*|============================
2 | | Додавання & Віднімання
3 | |============================
4 | */
5 | .box {
6 | width: 600px + 30px;
7 | width: 600px - 30px;
8 | }
9 | /*|============================
10 | | Множення & Ділення
11 | |============================
12 | */
13 | $vaule: 600px;
14 | .box {
15 | width: 600px * 5;
16 | width: 600px * 2 + 50px;
17 | width: 2 * (600px + 50px);
18 |
19 | width: $vaule / 5;
20 | width: (600px / 2);
21 | width: 600px / 3 + 100px;
22 | }
23 | /*|============================
24 | | Інтерполяція
25 | |============================
26 | */
27 | $margin: 100px;
28 | .box {
29 | width: $margin * 2;
30 | }
31 | .box {
32 | width: calc($margin * 2);
33 | width: calc(#{$margin} * 2);
34 | }
35 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-12/_mixins.scss:
--------------------------------------------------------------------------------
1 | @use "decimal" as *;
2 | @use "functions" as *;
3 |
4 | @mixin fonts($fs, $fw: null, $lh: null, $ls: null, $align: null) {
5 | @if $fs {
6 | font-size: $fs;
7 | }
8 |
9 | @if $fw {
10 | font-weight: $fw;
11 | }
12 |
13 | @if $lh {
14 | @if $lh == normal {
15 | line-height: normal;
16 | } @else {
17 | $lh: calc(strip-unit($lh) / strip-unit($fs));
18 | line-height: decimal-round($lh, 2);
19 | }
20 | }
21 |
22 | @if $ls {
23 | @if $ls == normal {
24 | letter-spacing: normal;
25 | } @else {
26 | $ls: calc(strip-unit($ls) / strip-unit($fs));
27 | letter-spacing: #{decimal-round($ls, 2)}em;
28 | }
29 | }
30 |
31 | @if $align {
32 | text-align: $align;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/img/icons/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-14/_colors.scss:
--------------------------------------------------------------------------------
1 | @use "sass:map";
2 |
3 | // |============================
4 | // | Набір змінних не повʼязаних
5 | // | між собою
6 | // |============================
7 | $color-primary: #8e3329;
8 | $color-accent: #d98328;
9 | $color-secondary: #5a1321;
10 | $color-foreground: #191919;
11 | $color-background: #e9e9e9;
12 |
13 | // |============================
14 | // | Обєʼднані значення (мапа)
15 | // |============================
16 | $colors: (
17 | "primary": #8e3329,
18 | "accent": #d98328,
19 | "secondary": #5a1321,
20 | "foreground": #191919,
21 | "background": #e9e9e9,
22 | );
23 |
24 | /* Отримуємо значення з мапи */
25 | body {
26 | background-color: map.get($colors, "background");
27 | }
28 |
29 | // Функція-утиліта для доступу до властивостей мапи
30 | @function get-color($key) {
31 | @return map.get($colors, $key);
32 | }
33 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-13/_list.scss:
--------------------------------------------------------------------------------
1 | @use "sass:list";
2 |
3 | // List examples
4 | $list: 8, 10, 12, 14, 16;
5 |
6 | $list: 1px solid red;
7 |
8 | // list.nth() function
9 | $numbers: 10px, 12px, 16px;
10 | @debug list.nth($numbers, 2); // 12px
11 |
12 | // list.length() function
13 | $colors: lightgreen, tomato, lightblue;
14 | @debug list.length($colors); // 3
15 |
16 | // use list with @each
17 | $sizes: 40px, 50px, 80px;
18 |
19 | @each $size in $sizes {
20 | .icon-#{$size} {
21 | font-size: $size;
22 | height: $size;
23 | width: $size;
24 | }
25 | }
26 |
27 | // use list with @for
28 | $button-types: ".btn-sm", ".btn-md", ".btn-lg", ".btn-xl";
29 |
30 | @mixin btn-size($types) {
31 | @for $i from 1 through list.length($types) {
32 | #{list.nth($types, $i)} {
33 | $factor: ($i * 5 - 5);
34 |
35 | padding: (5px + $factor) (10px + $factor);
36 | border-radius: (10px + $factor);
37 | }
38 | }
39 | }
40 |
41 | @include btn-size($button-types);
42 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-06/_combinators.scss:
--------------------------------------------------------------------------------
1 | // // descendant selector
2 | // div p {
3 | // /* Вибере всі елементи, які є нащадками для
*/
4 | // color: black;
5 | // }
6 |
7 | // // child selector
8 | // div > p {
9 | // /* Вибере всі
елементи, які є безпосередніми дітьми
*/
10 | // color: black;
11 | // }
12 |
13 | // // adjacent sibling selector
14 | // h2 + p {
15 | // /* Вибере елемент
, який є наступним сусідом
*/
16 | // color: black;
17 | // }
18 |
19 | // // general sibling selector
20 | // h2 ~ p {
21 | // /* Вибере всі
елементи, які є наступними сусідами
*/
22 | // color: black;
23 | // }
24 |
25 | /**
26 | |============================
27 | | Using combinators in SASS
28 | |============================
29 | */
30 | ul > {
31 | li {
32 | list-style: none;
33 | }
34 | }
35 |
36 | h2 {
37 | + p {
38 | border-top: 1px solid gray;
39 | }
40 | }
41 |
42 | p {
43 | ~ {
44 | span {
45 | opacity: 0.8;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/scss/base/_base.scss:
--------------------------------------------------------------------------------
1 | @use "../utilities/mixins";
2 |
3 | html {
4 | font-size: 8px;
5 | @include mixins.viewport-md {
6 | font-size: 10px;
7 | }
8 | }
9 | body {
10 | font-family: "Montserrat";
11 | background: var(--main-color);
12 | color: var(--main-text-color);
13 | font-size: 2.4rem;
14 | transition: background 0.2s ease, color 0.2s ease;
15 | }
16 |
17 | .wrapper {
18 | min-height: 100vh;
19 | text-align: center;
20 | display: flex;
21 | flex-flow: column;
22 | }
23 |
24 | .container {
25 | max-width: 1180px;
26 | margin: 0 auto;
27 | padding: 0 2rem;
28 | }
29 |
30 | .dark {
31 | color-scheme: dark;
32 | }
33 |
34 | .title {
35 | font-size: 4rem;
36 |
37 | span {
38 | font-size: 5rem;
39 | text-transform: uppercase;
40 | font-weight: 700;
41 | @include mixins.text-gradient;
42 | }
43 | }
44 |
45 | .footer {
46 | padding: 3rem 0;
47 | font-size: 1.6rem;
48 |
49 | a {
50 | text-decoration: none;
51 | color: var(--brand-color);
52 | transition: 0.2s ease;
53 | &:hover {
54 | color: var(--brand-light-color);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 GoIT
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-11/_if.scss:
--------------------------------------------------------------------------------
1 | @use "sass:math";
2 |
3 | // @if statement
4 | @mixin avatar($size, $circle: false) {
5 | width: $size;
6 | height: $size;
7 |
8 | @if $circle {
9 | border-radius: 50%;
10 | }
11 | }
12 |
13 | .square-avatar {
14 | @include avatar(100px);
15 | }
16 | .circle-avatar {
17 | @include avatar(100px, $circle: true);
18 | }
19 |
20 | // Conditional statements
21 | @mixin fonts($fs, $fw: null, $lh: null, $ls: null, $align: null) {
22 | font-size: $fs;
23 |
24 | @if $fw {
25 | font-weight: $fw;
26 | }
27 |
28 | @if $lh {
29 | @if $lh == normal {
30 | line-height: normal;
31 | } @else if math.unit($lh) == "px" {
32 | line-height: calc($lh / $fs);
33 | } @else {
34 | @error "$lh value #{$lh} is incorrect";
35 | }
36 | }
37 |
38 | @if $ls {
39 | @if $ls == normal {
40 | letter-spacing: normal;
41 | } @else {
42 | letter-spacing: #{calc($ls/$fs)}em;
43 | }
44 | }
45 |
46 | @if $align {
47 | text-align: $align;
48 | }
49 | }
50 |
51 | .title {
52 | // With keyword args
53 | @include fonts(20px, $fw: 600, $lh: 28px, $ls: 0.5px, $align: center);
54 | }
55 |
--------------------------------------------------------------------------------
/src/img/icons/gem.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/scss/main.scss:
--------------------------------------------------------------------------------
1 | // @use "utilities";
2 | // @use "base";
3 | // @use "layout";
4 | // @use "components";
5 |
6 | // Examples lesson 06
7 | // @use "--examples--/lesson-06/nesting";
8 | // @use "--examples--/lesson-06/combinators";
9 | // @use "--examples--/lesson-06/ampersand";
10 |
11 | // Examples lesson 07
12 | // @use "--examples--/lesson-07/math";
13 | // @use "--examples--/lesson-07/task-badge";
14 | // @use "base/fonts";
15 | // @use "components/task";
16 |
17 | // Examples lesson 09
18 | // @use "base/fonts";
19 | // @use "components/alert";
20 | // @use "--examples--/lesson-09/extend";
21 |
22 | // Examples lesson 10
23 | // @use "base/fonts";
24 | // @use "components/button";
25 | // @use "--examples--/lesson-10/mixins";
26 |
27 | // Examples lesson 11
28 | // @use "base/fonts";
29 | // @use "components/button";
30 | // @use "--examples--/lesson-11/if";
31 | // @use "--examples--/lesson-11/each";
32 | // @use "--examples--/lesson-11/for";
33 |
34 | // Examples lesson 12
35 | // @use "--examples--/lesson-12/examples";
36 | // @use "--examples--/lesson-12/functions";
37 |
38 | // Examples lesson 13
39 | // @use "--examples--/lesson-13/list";
40 |
41 | // Examples lesson 14
42 | @use "--examples--/lesson-14/map";
43 | @use "--examples--/lesson-14/alerts";
44 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-07/_task.scss:
--------------------------------------------------------------------------------
1 | body {
2 | min-height: 100vh;
3 |
4 | display: flex;
5 | align-items: center;
6 | justify-content: center;
7 | flex-direction: column;
8 | gap: 30px;
9 |
10 | background-color: #292932;
11 | }
12 |
13 | .task {
14 | display: flex;
15 | justify-content: space-between;
16 |
17 | width: 589px;
18 | padding: 24px;
19 |
20 | background-color: #1c1c24;
21 | border-radius: 12px;
22 | }
23 | .task-caption {
24 | margin-bottom: 8px;
25 |
26 | font-size: 16px;
27 | font-weight: 500;
28 | line-height: 24px;
29 | letter-spacing: 0.5px;
30 | color: #fafafb;
31 | }
32 | .task-deadline {
33 | margin-bottom: 18px;
34 |
35 | color: #fafafb;
36 | font-size: 14px;
37 | line-height: 20px; /* 142.857% */
38 | letter-spacing: 0.5px;
39 | }
40 | .task-deadline-date {
41 | color: #b5b5be;
42 | }
43 |
44 | .performer {
45 | display: flex;
46 | align-items: center;
47 | gap: 8px;
48 | }
49 | .performer-avatar {
50 | display: block;
51 | max-width: 100%;
52 | height: auto;
53 | }
54 | .performer-bio {
55 | color: #b5b5be;
56 | font-size: 14px;
57 | line-height: 20px;
58 | letter-spacing: 0.5px;
59 | }
60 |
61 | .task-badges {
62 | display: flex;
63 | flex-direction: column;
64 | justify-content: space-between;
65 | }
66 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import imagemin from "imagemin";
2 | import imageminWebp from "imagemin-webp";
3 | import path from "path";
4 | import { defineConfig } from "vite";
5 | import glob from "fast-glob";
6 | import { fileURLToPath } from "url";
7 | import { ViteImageOptimizer } from "vite-plugin-image-optimizer";
8 |
9 | export default defineConfig({
10 | plugins: [
11 | ViteImageOptimizer({
12 | png: {
13 | quality: 86,
14 | },
15 | jpeg: {
16 | quality: 86,
17 | },
18 | jpg: {
19 | quality: 86,
20 | },
21 | }),
22 | {
23 | ...imagemin(["./src/img/**/*.{jpg,png,jpeg}"], {
24 | destination: "./src/img/webp/",
25 | plugins: [imageminWebp({ quality: 86 })],
26 | }),
27 | apply: "serve",
28 | },
29 | ],
30 | build: {
31 | minify: false, // disable minification
32 | rollupOptions: {
33 | input: Object.fromEntries(
34 | glob
35 | .sync(["./*.html", "./pages/**/*.html"])
36 | .map((file) => [
37 | path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)),
38 | fileURLToPath(new URL(file, import.meta.url)),
39 | ])
40 | ),
41 | // output unminified CSS file
42 | output: {
43 | assetFileNames: "assets/[name].[ext]",
44 | },
45 | },
46 | },
47 | });
48 |
--------------------------------------------------------------------------------
/src/scss/layout/_main.scss:
--------------------------------------------------------------------------------
1 | @use "../utilities/mixins";
2 |
3 | .main {
4 | flex: 1;
5 | &-header {
6 | padding: 2.5rem 2rem;
7 | }
8 |
9 | &-logo {
10 | width: 300px;
11 | height: 300px;
12 | display: inline-block;
13 | position: relative;
14 | margin-bottom: 3rem;
15 |
16 | @include mixins.viewport-md {
17 | width: 360px;
18 | height: 360px;
19 | }
20 |
21 | &::before {
22 | content: "";
23 | position: absolute;
24 | z-index: -1;
25 | top: 50%;
26 | left: 50%;
27 | width: 70%;
28 | height: 70%;
29 | transform: translate(-50%, -50%);
30 | border-radius: 50%;
31 | background: var(--hero-name-background);
32 | filter: blur(72px);
33 | }
34 | }
35 |
36 | &-logo-img {
37 | width: 100%;
38 | height: 100%;
39 | }
40 |
41 | &-title {
42 | &-link {
43 | position: relative;
44 | transition: 200ms ease;
45 |
46 | &::before {
47 | content: "";
48 | position: absolute;
49 | bottom: 5px;
50 | left: 50%;
51 | transform: translateX(-50%) skewX(-10deg);
52 | z-index: -1;
53 |
54 | width: 105%;
55 | height: 20%;
56 | background-color: var(--brand-light-color);
57 |
58 | transition: 200ms ease;
59 | }
60 |
61 | &:hover,
62 | &:focus {
63 | color: var(--brand-light-color);
64 |
65 | &::before {
66 | background-color: var(--main-text-color);
67 | }
68 | }
69 | }
70 | }
71 |
72 | &-badges {
73 | margin: 3rem 0 5rem;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-12/_decimal.scss:
--------------------------------------------------------------------------------
1 | // _decimal.scss | MIT License | gist.github.com/terkel/4373420
2 |
3 | // Round a number to specified digits.
4 | //
5 | // @param {Number} $number A number to round
6 | // @param {Number} [$digits:0] Digits to output
7 | // @param {String} [$mode:round] (round|ceil|floor) How to round a number
8 | // @return {Number} A rounded number
9 | // @example
10 | // decimal-round(0.333) => 0
11 | // decimal-round(0.333, 1) => 0.3
12 | // decimal-round(0.333, 2) => 0.33
13 | // decimal-round(0.666) => 1
14 | // decimal-round(0.666, 1) => 0.7
15 | // decimal-round(0.666, 2) => 0.67
16 | //
17 | @use "sass:math";
18 |
19 | @function decimal-round($number, $digits: 0, $mode: round) {
20 | $n: 1;
21 | // $number must be a number
22 | @if type-of($number) != number {
23 | @warn '#{ $number } is not a number.';
24 | @return $number;
25 | }
26 | // $digits must be a unitless number
27 | @if type-of($digits) != number {
28 | @warn '#{ $digits } is not a number.';
29 | @return $number;
30 | } @else if not unitless($digits) {
31 | @warn '#{ $digits } has a unit.';
32 | @return $number;
33 | }
34 | @if $digits > 0 {
35 | @for $i from 1 through $digits {
36 | $n: $n * 10;
37 | }
38 | }
39 | @if $mode == round {
40 | @return math.div(math.round($number * $n), $n);
41 | } @else if $mode == ceil {
42 | @return math.div(math.ceil($number * $n), $n);
43 | } @else if $mode == floor {
44 | @return math.div(math.floor($number * $n), $n);
45 | } @else {
46 | @warn '#{ $mode } is undefined keyword.';
47 | @return $number;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/img/icons/info.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/img/icons/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/demo/project-structure.md:
--------------------------------------------------------------------------------
1 | ```scss
2 | sass/
3 | |
4 | ├── base/
5 | | ├── _base.scss // # Набір базових стилей
6 | | ├── _reset.scss // # Скидання стилей браузера
7 | | ├── _typography.scss // # Текстові стилі
8 | | ├── _animations.scss // # Анімації (додані через @keyframes)
9 | | … // # і таке інше
10 | |
11 | ├── components/
12 | | ├── _buttons.scss // # Кнопки
13 | | ├── _carousel.scss // # Слайдер
14 | | ├── _cover.scss // # Обкладинка
15 | | ├── _dropdown.scss // # Випадаюче меню
16 | | … // # і таке інше
17 | |
18 | ├── layout/
19 | | ├── _navigation.scss // # Навігація
20 | | ├── _grid.scss // # Сітка
21 | | ├── _header.scss // # Хедер
22 | | ├── _footer.scss // # Футер
23 | | ├── _sidebar.scss // # Сайдбар
24 | | ├── _forms.scss // # Форми
25 | | … // # і таке інше
26 | |
27 | ├── pages/
28 | | ├── _home.scss // # Специфічні стилі сторінки Home
29 | | ├── _contact.scss // # Специфічні стилі сторінки Contact
30 | | … // # і таке інше
31 | |
32 | ├── themes/
33 | | ├── _theme.scss // # Тема за змовчуванням
34 | | ├── _admin.scss // # Тема для адміністратора сайту
35 | | ├── _manager.scss // # Тема для менеджера сайту
36 | | … // # і таке інше
37 | |
38 | ├── vendors/
39 | | ├── _bootstrap.scss // # Bootstrap бібліотека
40 | | ├── _modern-normalize.scss // # Нормалізація стилей
41 | | … // # і таке інше
42 | |
43 | ├── utils/
44 | | ├── _variables.scss // # Sass змінні
45 | | ├── _functions.scss // # Sass функції
46 | | ├── _mixins.scss // # Sass міксини
47 | | ├── _placeholders.scss // # Sass плейсхолдери
48 | |
49 | └── main.scss // # Головний Sass файл
50 | ```
51 |
--------------------------------------------------------------------------------
/src/img/icons/check.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-09/_extend.scss:
--------------------------------------------------------------------------------
1 | // $primary: #f07f2e;
2 | // $success: #82c43c;
3 | // $primary: #4e75ff;
4 |
5 | // Approach 1
6 | // .notification {
7 | // display: flex;
8 | // align-items: center;
9 | // gap: 20px;
10 |
11 | // width: 480px;
12 | // padding: 20px;
13 |
14 | // font-family: Montserrat;
15 | // color: #fafafb;
16 | // font-size: 16px;
17 | // line-height: 20px; /* 125% */
18 | // letter-spacing: 0.5px;
19 |
20 | // background-color: #92929d;
21 | // border-radius: 6px;
22 | // }
23 | // .notification-primary {
24 | // background-color: #f07f2e;
25 | // }
26 |
27 | // .notification-success {
28 | // background-color: #82c43c;
29 | // }
30 |
31 | // .notification-info {
32 | // background-color: #4e75ff;
33 | // }
34 |
35 | // Approach 2
36 | // .notification {
37 | // display: flex;
38 | // align-items: center;
39 | // gap: 20px;
40 |
41 | // width: 480px;
42 | // padding: 20px;
43 |
44 | // font-family: Montserrat;
45 | // color: #fafafb;
46 | // font-size: 16px;
47 | // line-height: 20px; /* 125% */
48 | // letter-spacing: 0.5px;
49 |
50 | // background-color: #92929d;
51 | // border-radius: 6px;
52 | // }
53 |
54 | // .notification-primary {
55 | // @extend .notification;
56 |
57 | // background-color: #f07f2e;
58 | // }
59 |
60 | // .notification-success {
61 | // @extend .notification;
62 |
63 | // background-color: #82c43c;
64 | // }
65 |
66 | // .notification-info {
67 | // @extend .notification;
68 |
69 | // background-color: #4e75ff;
70 | // }
71 |
72 | // Approach 3
73 | %notification {
74 | display: flex;
75 | align-items: center;
76 | gap: 20px;
77 |
78 | width: 480px;
79 | padding: 20px;
80 |
81 | font-family: Montserrat;
82 | color: #fafafb;
83 | font-size: 16px;
84 | line-height: 20px; /* 125% */
85 | letter-spacing: 0.5px;
86 |
87 | background-color: #92929d;
88 | border-radius: 6px;
89 | }
90 |
91 | .notification-primary {
92 | @extend %notification;
93 |
94 | background-color: #f07f2e;
95 | }
96 |
97 | .notification-success {
98 | @extend %notification;
99 |
100 | background-color: #82c43c;
101 | }
102 |
103 | .notification-info {
104 | @extend %notification;
105 |
106 | background-color: #4e75ff;
107 | }
108 |
--------------------------------------------------------------------------------
/src/img/icons/warning.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/img/icons/danger.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/scss/base/_reset.scss:
--------------------------------------------------------------------------------
1 | /***
2 | The new CSS reset - version 1.11 (last updated 20.9.2023)
3 | GitHub page: https://github.com/elad2412/the-new-css-reset
4 | ***/
5 |
6 | /*
7 | Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
8 | - The "symbol *" part is to solve Firefox SVG sprite bug
9 | - The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36)
10 | */
11 | *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
12 | all: unset;
13 | display: revert;
14 | }
15 |
16 | /* Preferred box-sizing value */
17 | *,
18 | *::before,
19 | *::after {
20 | box-sizing: border-box;
21 | }
22 |
23 | /* Fix mobile Safari increase font-size on landscape mode */
24 | html {
25 | -moz-text-size-adjust: none;
26 | -webkit-text-size-adjust: none;
27 | text-size-adjust: none;
28 | }
29 |
30 | /* Reapply the pointer cursor for anchor tags */
31 | a,
32 | button {
33 | cursor: revert;
34 | }
35 |
36 | /* Remove list styles (bullets/numbers) */
37 | ol,
38 | ul,
39 | menu {
40 | list-style: none;
41 | }
42 |
43 | /* For images to not be able to exceed their container */
44 | img {
45 | max-inline-size: 100%;
46 | max-block-size: 100%;
47 | }
48 |
49 | /* removes spacing between cells in tables */
50 | table {
51 | border-collapse: collapse;
52 | }
53 |
54 | /* Safari - solving issue when using user-select:none on the text input doesn't working */
55 | input,
56 | textarea {
57 | -webkit-user-select: auto;
58 | }
59 |
60 | /* revert the 'white-space' property for textarea elements on Safari */
61 | textarea {
62 | white-space: revert;
63 | }
64 |
65 | /* minimum style to allow to style meter element */
66 | meter {
67 | -webkit-appearance: revert;
68 | appearance: revert;
69 | }
70 |
71 | /* preformatted text - use only for this feature */
72 | :where(pre) {
73 | all: revert;
74 | box-sizing: border-box;
75 | }
76 |
77 | /* reset default text opacity of input placeholder */
78 | ::placeholder {
79 | color: unset;
80 | }
81 |
82 | /* remove default dot (•) sign */
83 | ::marker {
84 | content: initial;
85 | }
86 |
87 | /* fix the feature of 'hidden' attribute.
88 | display:revert; revert to element instead of attribute */
89 | :where([hidden]) {
90 | display: none;
91 | }
92 |
93 | /* revert for bug in Chromium browsers
94 | - fix for the content editable attribute will work properly.
95 | - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/
96 | :where([contenteditable]:not([contenteditable="false"])) {
97 | -moz-user-modify: read-write;
98 | -webkit-user-modify: read-write;
99 | overflow-wrap: break-word;
100 | -webkit-line-break: after-white-space;
101 | -webkit-user-select: auto;
102 | }
103 |
104 | /* apply back the draggable feature - exist only in Chromium and Safari */
105 | :where([draggable="true"]) {
106 | -webkit-user-drag: element;
107 | }
108 |
109 | /* Revert Modal native behavior */
110 | :where(dialog:modal) {
111 | all: revert;
112 | box-sizing: border-box;
113 | }
114 |
--------------------------------------------------------------------------------
/src/scss/--examples--/lesson-10/_mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin frame-size($width, $height: $width) {
2 | width: $width;
3 | height: $height;
4 | }
5 |
6 | %size {
7 | width: 150px;
8 | height: 150px;
9 | }
10 |
11 | .avatar {
12 | @include frame-size(150px);
13 | @extend %size;
14 |
15 | border-radius: 50%;
16 | }
17 |
18 | .icon {
19 | @include frame-size(50px);
20 | @extend %size;
21 |
22 | border: 2px solid lightblue;
23 | }
24 |
25 | // Arguments
26 | @mixin position-center {
27 | position: absolute;
28 | top: 50%;
29 | left: 50%;
30 | transform: translate(-50%, -50%);
31 | }
32 |
33 | .decoration {
34 | @include position-center;
35 | }
36 |
37 | @mixin position($position-type, $position-x, $position-y, $offset-x, $offset-y) {
38 | position: $position-type;
39 | top: $position-y;
40 | left: $position-x;
41 | transform: translate($offset-x, $offset-y);
42 | }
43 |
44 | .decoration {
45 | @include position(absolute, 50%, 50%, -50%, -50%);
46 | }
47 |
48 | @mixin position(
49 | $layer-index,
50 | $display,
51 | // обовʼязковий параметр
52 | $position-type: absolute,
53 | $position-x: 50%,
54 | $position-y: $position-x,
55 | $offset-x: $position-x,
56 | $offset-y: $position-x
57 | ) {
58 | position: $position-type;
59 | top: $position-y;
60 | left: $position-x;
61 | transform: translate(($offset-x * -1), ($offset-y * -1));
62 | z-index: $layer-index;
63 | display: $display;
64 | }
65 |
66 | .decoration {
67 | @include position($offset-y: 70%, $layer-index: 100, $display: block);
68 | }
69 |
70 | %btn {
71 | font-family: Montserrat;
72 | font-size: 14px;
73 | font-weight: 500;
74 | line-height: 20px; /* 142.857% */
75 | letter-spacing: 0.5px;
76 | color: #fafafb;
77 |
78 | background-color: #f07f2e;
79 | border: none;
80 | cursor: pointer;
81 | transition: 300ms;
82 |
83 | &:hover,
84 | &:focus {
85 | background-color: #f15c27;
86 | box-shadow: 0px 4px 10px 0px rgba(240, 127, 46, 0.25);
87 | }
88 | }
89 |
90 | @mixin btn-size($args...) {
91 | @for $i from 1 through length($args) {
92 | #{nth($args, $i)} {
93 | $factor: ($i * 4 - 4);
94 |
95 | @extend %btn;
96 |
97 | padding: (4px + $factor) (8px + $factor);
98 | border-radius: (8px + $factor);
99 | }
100 | }
101 | }
102 |
103 | @include btn-size(".btn-sm", ".btn-md", ".btn-lg", ".btn-xl");
104 |
105 | @use "sass:meta";
106 |
107 | @mixin btn-type($types...) {
108 | // $types: (
109 | // $success: lightgreen,
110 | // $error: tomato,
111 | // $info: lightblue,
112 | // );
113 |
114 | @each $name, $color in meta.keywords($types) {
115 | .btn-#{$name} {
116 | border: 2px solid $color;
117 | color: $color;
118 | }
119 | }
120 | }
121 |
122 | @include btn-type($success: lightgreen, $error: tomato, $info: lightblue);
123 |
124 | @mixin hover($state) {
125 | &:not([#{$state}]):hover {
126 | @content;
127 | }
128 | }
129 |
130 | .button {
131 | background-color: white;
132 | border: 1px solid darkblue;
133 |
134 | @include hover($state: disabled) {
135 | color: white;
136 | background-color: darkblue;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/img/icons.svg:
--------------------------------------------------------------------------------
1 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple starter template for Sass
2 |
3 | 
4 |
5 | ## Vanilla App Template
6 |
7 | Цей проект було створено за допомогою Vite. Для знайомства та налаштування
8 | додаткових можливостей [звернись до документації](https://vitejs.dev/).
9 |
10 | Ключові особливості цього шаблону:
11 |
12 | **Build Tools:** Vite.js
13 | **Plugins:** Autoprefixer, PostCSS Sort Media Queries
14 | **Styles:** SCSS
15 | **Reset:** \_reset.scss (Based on The New Reset CSS)
16 |
17 | ## Створення репозиторію за шаблоном
18 |
19 | Використовуй цей репозиторій організації GoIT як шаблон для створення
20 | репозиторію свого проекту. Для цього натисни на кнопку `«Use this template»` і
21 | обери опцію `«Create a new repository»`, як показано на зображенні.
22 |
23 | 
24 |
25 | На наступному етапі відкриється сторінка створення нового репозиторію. Заповни
26 | поле його імені, переконайся, що репозиторій публічний, після чого натисни
27 | кнопку `«Create repository from template»`.
28 |
29 | 
30 |
31 | Після того, як репозиторій буде створено, необхідно перейти в налаштування
32 | створеного репозиторію на вкладку `Settings` > `Actions` > `General` як показано
33 | на зображенні.
34 |
35 | 
36 |
37 | Проскроливши сторінку до самого кінця, в секції `«Workflow permissions»` обери
38 | опцію `«Read and write permissions»` і постав галочку в чекбоксі. Це необхідно
39 | для автоматизації процесу деплою проекту.
40 |
41 | 
42 |
43 | Тепер у тебе є особистий репозиторій проекту, зі структурою файлів та папок
44 | репозиторію-шаблону. Далі працюй з ним, як з будь-яким іншим особистим
45 | репозиторієм, клонуй його собі на комп'ютер, пиши код, роби коміти та відправляй
46 | їх на GitHub!
47 |
48 | ## Підготовка до роботи
49 |
50 | 1. Переконайся, що на комп'ютері встановлено LTS-версію Node.js.
51 | [Скачай та встанови](https://nodejs.org/en/) її якщо необхідно.
52 | 2. Встанови базові залежності проекту в терміналі командою `npm install`.
53 | 3. Запусти режим розробки, виконавши в терміналі команду `npm run dev`.
54 | 4. Перейдіть у браузері за адресою
55 | [http://localhost:5173](http://localhost:5173). Ця сторінка буде автоматично
56 | перезавантажуватись після збереження змін у файли проекту.
57 | 5. Для перегляду результуючого СSS файлу виконай команду
58 | `npx vite build --watch` та перейди в папку `dist/assets`
59 |
60 | ## Структура проекту. Файли і папки
61 |
62 | This is the structure of the project:
63 |
64 | ```plaintext
65 | /
66 | ├── demo # Папка для файлів цієї інструкції
67 | ├── dist # Результуючий код
68 | ├── node_modules # Node.js залежності для проекту
69 | ├── public # Файли для публічного доступу та використання
70 | ├── src # Вихідний код
71 | │ ├── fonts # Папка для ваших шрифтів
72 | │ ├── img # Папка для ваших зображень
73 | │ ├── js # Файли Javascript вашого проекту
74 | │ ├── scss # Стилі SCSS для вашого проекту
75 | ├── .gitignore # Перелік файлів та папок, які ігнорує Git
76 | ├── index.html # Файл HTML для вашого проекту
77 | ├── LICENSE # Файл ліцензії для вашого проекту
78 | ├── package-lock.json # Файл з поточними версіями залежностей для вашого проекту
79 | ├── package.json # Визначає метадані вашого проекту і його залежності
80 | ├── postcss.config.cjs # Конфігурація для PostCSS
81 | ├── README.md # Цей файл 😎
82 | ├── vite.config.js # Конфігурація бандлера Vite
83 | ```
84 |
85 | ## Подальші кроки
86 |
87 | Після клонування шаблону обов’язково очистіть і оновіть наступні файли/папки:
88 |
89 | 1. Очистіть файл README.md.
90 | 2. Адаптуйте файл LICENSE до свого проекту.
91 | 3. Очистіть `public/sass.svg`, папки `demo/`, `src/img/**/*`, `src/fonts/**/*`, а також `src/scss/**.*`, окрім файлів `style.scss` та `_reset.scss`.
92 | 4. Видаліть вміст із файлу `src/scss/style.scss`, окрім `@use "reset.scss";`.
93 | 5. У файлі `src/js/main.js`, залиште лише цей рядок з імпортом: `import '../scss/style.scss';`.
94 |
95 | ## Деплой
96 |
97 | Продакшн версія проекту буде автоматично збиратися та деплоїтись на GitHub
98 | Pages, у гілку `gh-pages`, щоразу, коли оновлюється гілка `main`. Наприклад,
99 | після прямого пуша або прийнятого пул-реквесту. Для цього необхідно у файлі
100 | `package.json` змінити значення прапора `--base=//`, для команди `build`,
101 | замінивши `` на назву свого репозиторію, та відправити зміни на GitHub.
102 |
103 | ```json
104 | "build": "vite build --base=//",
105 | ```
106 |
107 | Далі необхідно зайти в налаштування GitHub-репозиторію (`Settings` > `Pages`) та
108 | виставити роздачу продакшн версії файлів з папки `/root` гілки `gh-pages`, якщо
109 | це не було зроблено автоматично.
110 |
111 | 
112 |
113 | ## License
114 |
115 | Цей шаблон створено під [MIT License](LICENSE).
116 |
117 | **Thank you and happy coding!** 💻
118 |
--------------------------------------------------------------------------------
/public/sass.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------