@mr.slonn/my-scss-theme 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -0
- package/index.scss +1 -0
- package/package.json +10 -0
- package/scss/.sassdocrc +85 -0
- package/scss/_font-vars.scss +25 -0
- package/scss/_fonts.scss +139 -0
- package/scss/abstracts/_animations.scss +819 -0
- package/scss/abstracts/_breakpoints.scss +865 -0
- package/scss/abstracts/_colors.scss +256 -0
- package/scss/abstracts/_functions.scss +3 -0
- package/scss/abstracts/_grid.scss +816 -0
- package/scss/abstracts/_index.scss +134 -0
- package/scss/abstracts/_mixins.scss +1142 -0
- package/scss/abstracts/_patterns.scss +657 -0
- package/scss/abstracts/_radius.scss +279 -0
- package/scss/abstracts/_search-form.scss +271 -0
- package/scss/abstracts/_spacing.scss +158 -0
- package/scss/abstracts/_typography.scss +477 -0
- package/scss/abstracts/_utilities.scss +0 -0
- package/scss/abstracts/_variables.scss +3 -0
- package/scss/abstracts/breadcrumb/_base.scss +194 -0
- package/scss/abstracts/breadcrumb/_index.scss +12 -0
- package/scss/abstracts/breadcrumb/_variables.scss +54 -0
- package/scss/abstracts/buttons/_base.scss +92 -0
- package/scss/abstracts/buttons/_index.scss +31 -0
- package/scss/abstracts/buttons/_modifiers.scss +114 -0
- package/scss/abstracts/buttons/_variables.scss +98 -0
- package/scss/abstracts/buttons/_variants.scss +295 -0
- package/scss/abstracts/callout/_base.scss +142 -0
- package/scss/abstracts/callout/_index.scss +23 -0
- package/scss/abstracts/callout/_variables.scss +27 -0
- package/scss/abstracts/cards/_base.scss +74 -0
- package/scss/abstracts/cards/_blur.scss +65 -0
- package/scss/abstracts/cards/_featured.scss +363 -0
- package/scss/abstracts/cards/_hover.scss +99 -0
- package/scss/abstracts/cards/_index.scss +51 -0
- package/scss/abstracts/cards/_parts.scss +135 -0
- package/scss/abstracts/cards/_sizes.scss +52 -0
- package/scss/abstracts/cards/_variables.scss +72 -0
- package/scss/abstracts/cards/_variants.scss +143 -0
- package/scss/abstracts/cards/_vertical.scss +218 -0
- package/scss/abstracts/chip/_base.scss +99 -0
- package/scss/abstracts/chip/_icon.scss +73 -0
- package/scss/abstracts/chip/_index.scss +21 -0
- package/scss/abstracts/chip/_variables.scss +57 -0
- package/scss/abstracts/chip/_variants.scss +98 -0
- package/scss/abstracts/file-card/_base.scss +326 -0
- package/scss/abstracts/file-card/_index.scss +12 -0
- package/scss/abstracts/file-card/_variables.scss +79 -0
- package/scss/abstracts/hero/_base.scss +182 -0
- package/scss/abstracts/hero/_index.scss +23 -0
- package/scss/abstracts/hero/_variables.scss +59 -0
- package/scss/abstracts/info-card/_base.scss +152 -0
- package/scss/abstracts/info-card/_index.scss +12 -0
- package/scss/abstracts/info-card/_variables.scss +44 -0
- package/scss/abstracts/news-card/_base.scss +143 -0
- package/scss/abstracts/news-card/_compact.scss +24 -0
- package/scss/abstracts/news-card/_featured.scss +83 -0
- package/scss/abstracts/news-card/_index.scss +31 -0
- package/scss/abstracts/news-card/_variables.scss +44 -0
- package/scss/abstracts/project-card/_base.scss +109 -0
- package/scss/abstracts/project-card/_index.scss +23 -0
- package/scss/abstracts/project-card/_variables.scss +20 -0
- package/scss/abstracts/search-form/_base.scss +132 -0
- package/scss/abstracts/search-form/_composite.scss +54 -0
- package/scss/abstracts/search-form/_index.scss +31 -0
- package/scss/abstracts/search-form/_theme.scss +89 -0
- package/scss/abstracts/search-form/_variables.scss +39 -0
- package/scss/abstracts/section-title/_base.scss +127 -0
- package/scss/abstracts/section-title/_index.scss +23 -0
- package/scss/abstracts/section-title/_variables.scss +27 -0
- package/scss/abstracts/service-card/_base.scss +77 -0
- package/scss/abstracts/service-card/_index.scss +23 -0
- package/scss/abstracts/service-card/_variables.scss +23 -0
- package/scss/abstracts/sidebar-menu/_base.scss +148 -0
- package/scss/abstracts/sidebar-menu/_index.scss +12 -0
- package/scss/abstracts/sidebar-menu/_variables.scss +55 -0
- package/scss/abstracts/stats-card/_base.scss +99 -0
- package/scss/abstracts/stats-card/_index.scss +23 -0
- package/scss/abstracts/stats-card/_variables.scss +32 -0
- package/scss/api.scss +12 -0
- package/scss/components/_breadcrumb.scss +140 -0
- package/scss/components/_buttons.scss +226 -0
- package/scss/components/_callout.scss +118 -0
- package/scss/components/_chip.scss +56 -0
- package/scss/components/_file-card.scss +182 -0
- package/scss/components/_hero.scss +103 -0
- package/scss/components/_index.scss +110 -0
- package/scss/components/_info-card.scss +103 -0
- package/scss/components/_news-card-compact.scss +33 -0
- package/scss/components/_news-card-featured.scss +49 -0
- package/scss/components/_news-card.scss +303 -0
- package/scss/components/_project-card.scss +93 -0
- package/scss/components/_search-form.scss +181 -0
- package/scss/components/_section-title.scss +94 -0
- package/scss/components/_service-card.scss +83 -0
- package/scss/components/_sidebar-menu.scss +82 -0
- package/scss/components/_stats-card.scss +92 -0
- package/scss/components/_tag.scss +144 -0
- package/scss/components/_top-nav.scss +537 -0
- package/scss/main.scss +73 -0
- package/scss/utilities/_index.scss +40 -0
- package/scss/utilities/_visibility.scss +224 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
////
|
|
2
|
+
/// Система сетки темы MOEXP
|
|
3
|
+
/// CSS Grid с Flexbox fallback для старых браузеров
|
|
4
|
+
/// @group grid
|
|
5
|
+
/// @author MOEXP Team
|
|
6
|
+
////
|
|
7
|
+
|
|
8
|
+
// ============================================
|
|
9
|
+
// GRID SYSTEM WITH FLEX FALLBACK (FIXED v3)
|
|
10
|
+
// local\common\theme-moexp\src\scss\abstracts\_grid.scss
|
|
11
|
+
// ============================================
|
|
12
|
+
|
|
13
|
+
@use "sass:math";
|
|
14
|
+
@use "sass:map";
|
|
15
|
+
@use "sass:list";
|
|
16
|
+
@use "sass:meta";
|
|
17
|
+
@use "spacing";
|
|
18
|
+
@use "breakpoints";
|
|
19
|
+
|
|
20
|
+
// ─────────────────────────────────────────
|
|
21
|
+
// ПЕРЕМЕННЫЕ
|
|
22
|
+
// ─────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
/// Количество колонок в сетке по умолчанию
|
|
25
|
+
/// @type Number
|
|
26
|
+
/// @group grid-variables
|
|
27
|
+
$grid-columns: 12 !default;
|
|
28
|
+
|
|
29
|
+
/// Gap по умолчанию (1rem / 16px)
|
|
30
|
+
/// @type Number
|
|
31
|
+
/// @group grid-variables
|
|
32
|
+
$grid-gap-default: spacing.$gap-md !default;
|
|
33
|
+
|
|
34
|
+
// ─────────────────────────────────────────
|
|
35
|
+
// ВСПОМОГАТЕЛЬНАЯ ФУНКЦИЯ
|
|
36
|
+
// ─────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
/// Вычисляет ширину элемента для flex fallback
|
|
39
|
+
/// @param {Number} $columns - Количество колонок
|
|
40
|
+
/// @param {Number} $gap - Gap между элементами
|
|
41
|
+
/// @return {String} calc() значение ширины
|
|
42
|
+
/// @example scss
|
|
43
|
+
/// width: _flex-width(3, 1rem);
|
|
44
|
+
/// // => calc(33.3333% - 1rem)
|
|
45
|
+
/// @group grid-functions
|
|
46
|
+
/// @access private
|
|
47
|
+
@function _flex-width($columns, $gap) {
|
|
48
|
+
@if $columns == 1 {
|
|
49
|
+
@return 100%;
|
|
50
|
+
}
|
|
51
|
+
@return calc(#{math.percentage(math.div(1, $columns))} - #{$gap});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─────────────────────────────────────────
|
|
55
|
+
// GRID ITEM
|
|
56
|
+
// ─────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
/// Базовые стили для элемента сетки
|
|
59
|
+
/// Предотвращает overflow и проблемы с min-width
|
|
60
|
+
/// @example scss
|
|
61
|
+
/// .grid__item {
|
|
62
|
+
/// @include grid-item;
|
|
63
|
+
/// }
|
|
64
|
+
/// @output box-sizing, min-width, min-height
|
|
65
|
+
/// @group grid-item
|
|
66
|
+
/// @access public
|
|
67
|
+
@mixin grid-item {
|
|
68
|
+
box-sizing: border-box;
|
|
69
|
+
min-width: 0;
|
|
70
|
+
min-height: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─────────────────────────────────────────
|
|
74
|
+
// БАЗОВЫЙ GRID КОНТЕЙНЕР
|
|
75
|
+
// ─────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
/// Базовый grid контейнер с фиксированным количеством колонок
|
|
78
|
+
/// Flexbox fallback для IE11 и старых браузеров
|
|
79
|
+
/// @param {Number} $columns [3] - Количество колонок
|
|
80
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap между элементами
|
|
81
|
+
/// @param {String} $align [stretch] - align-items значение
|
|
82
|
+
/// @param {String} $selector ["> *"] - Селектор дочерних элементов
|
|
83
|
+
/// @param {Boolean} $test [false] - Отключить @supports для тестирования fallback
|
|
84
|
+
/// @require {function} _flex-width
|
|
85
|
+
/// @example scss - 4 колонки
|
|
86
|
+
/// .products {
|
|
87
|
+
/// @include grid-container(4, spacing.$gap-lg);
|
|
88
|
+
/// }
|
|
89
|
+
/// @example scss - С кастомным селектором
|
|
90
|
+
/// .cards {
|
|
91
|
+
/// @include grid-container(3, 1rem, stretch, ".card");
|
|
92
|
+
/// }
|
|
93
|
+
/// @output Flexbox fallback + CSS Grid через @supports
|
|
94
|
+
/// @group grid-container
|
|
95
|
+
/// @access public
|
|
96
|
+
@mixin grid-container($columns: 3, $gap: $grid-gap-default, $align: stretch, $selector: "> *", $test: false) {
|
|
97
|
+
$gap-half: math.div($gap, 2);
|
|
98
|
+
|
|
99
|
+
// FALLBACK: Flexbox
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-wrap: wrap;
|
|
102
|
+
align-items: $align;
|
|
103
|
+
margin: -#{$gap-half};
|
|
104
|
+
|
|
105
|
+
#{$selector} {
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
flex: 0 0 _flex-width($columns, $gap);
|
|
108
|
+
width: _flex-width($columns, $gap);
|
|
109
|
+
max-width: _flex-width($columns, $gap);
|
|
110
|
+
min-width: 0;
|
|
111
|
+
margin: $gap-half;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// MODERN: CSS Grid
|
|
115
|
+
@if $test != true {
|
|
116
|
+
@supports (display: grid) {
|
|
117
|
+
display: grid;
|
|
118
|
+
grid-template-columns: repeat($columns, 1fr);
|
|
119
|
+
gap: $gap;
|
|
120
|
+
margin: 0;
|
|
121
|
+
|
|
122
|
+
#{$selector} {
|
|
123
|
+
width: auto;
|
|
124
|
+
max-width: none;
|
|
125
|
+
margin: 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ─────────────────────────────────────────
|
|
132
|
+
// GRID AUTO-FIT
|
|
133
|
+
// ─────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
/// Grid с auto-fit — колонки автоматически подстраиваются под ширину
|
|
136
|
+
/// @param {Number} $min-width [280px] - Минимальная ширина колонки
|
|
137
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap между элементами
|
|
138
|
+
/// @param {Number} $max-columns [4] - Максимум колонок (для fallback)
|
|
139
|
+
/// @param {String} $selector ["> *"] - Селектор дочерних элементов
|
|
140
|
+
/// @param {Boolean} $test [false] - Отключить @supports для тестирования
|
|
141
|
+
/// @require {function} _flex-width
|
|
142
|
+
/// @require {mixin} breakpoints.lg
|
|
143
|
+
/// @example scss - Карточки минимум 300px
|
|
144
|
+
/// .cards-grid {
|
|
145
|
+
/// @include grid-auto-fit(300px, spacing.$gap-lg);
|
|
146
|
+
/// }
|
|
147
|
+
/// @example scss - Галерея с мелкими элементами
|
|
148
|
+
/// .gallery {
|
|
149
|
+
/// @include grid-auto-fit(150px, spacing.$gap-sm, 6);
|
|
150
|
+
/// }
|
|
151
|
+
/// @output Flex fallback + grid auto-fit через @supports
|
|
152
|
+
/// @group grid-container
|
|
153
|
+
/// @access public
|
|
154
|
+
@mixin grid-auto-fit($min-width: 280px, $gap: $grid-gap-default, $max-columns: 4, $selector: "> *", $test: false) {
|
|
155
|
+
$gap-half: math.div($gap, 2);
|
|
156
|
+
|
|
157
|
+
// FALLBACK
|
|
158
|
+
display: flex;
|
|
159
|
+
flex-wrap: wrap;
|
|
160
|
+
margin: -#{$gap-half};
|
|
161
|
+
|
|
162
|
+
#{$selector} {
|
|
163
|
+
box-sizing: border-box;
|
|
164
|
+
flex: 1 1 $min-width;
|
|
165
|
+
min-width: $min-width;
|
|
166
|
+
max-width: 100%;
|
|
167
|
+
margin: $gap-half;
|
|
168
|
+
|
|
169
|
+
@if $max-columns {
|
|
170
|
+
@include breakpoints.lg {
|
|
171
|
+
max-width: _flex-width($max-columns, $gap);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// MODERN
|
|
177
|
+
@if $test != true {
|
|
178
|
+
@supports (display: grid) {
|
|
179
|
+
display: grid;
|
|
180
|
+
grid-template-columns: repeat(auto-fit, minmax($min-width, 1fr));
|
|
181
|
+
gap: $gap;
|
|
182
|
+
margin: 0;
|
|
183
|
+
|
|
184
|
+
#{$selector} {
|
|
185
|
+
min-width: 0;
|
|
186
|
+
max-width: none;
|
|
187
|
+
margin: 0;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ─────────────────────────────────────────
|
|
194
|
+
// РЕСПОНСИВНЫЙ GRID
|
|
195
|
+
// ─────────────────────────────────────────
|
|
196
|
+
|
|
197
|
+
/// Респонсивный grid с разным количеством колонок на брейкпоинтах
|
|
198
|
+
/// @param {Map} $breakpoint-columns - Карта (breakpoint: columns)
|
|
199
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap между элементами
|
|
200
|
+
/// @param {String} $selector ["> *"] - Селектор дочерних элементов
|
|
201
|
+
/// @param {Boolean} $test [false] - Отключить @supports для тестирования
|
|
202
|
+
/// @require {function} _flex-width
|
|
203
|
+
/// @require {mixin} breakpoints.media
|
|
204
|
+
/// @example scss - 1→2→3 колонки
|
|
205
|
+
/// .services {
|
|
206
|
+
/// @include grid-responsive((
|
|
207
|
+
/// xs: 1,
|
|
208
|
+
/// md: 2,
|
|
209
|
+
/// lg: 3
|
|
210
|
+
/// ));
|
|
211
|
+
/// }
|
|
212
|
+
/// @example scss - Сложная раскладка
|
|
213
|
+
/// .products {
|
|
214
|
+
/// @include grid-responsive((
|
|
215
|
+
/// xs: 1,
|
|
216
|
+
/// sm: 2,
|
|
217
|
+
/// lg: 3,
|
|
218
|
+
/// xl: 4,
|
|
219
|
+
/// xxl: 5
|
|
220
|
+
/// ), spacing.$gap-lg);
|
|
221
|
+
/// }
|
|
222
|
+
/// @output Flex fallback с медиа-запросами + CSS Grid через @supports
|
|
223
|
+
/// @group grid-responsive
|
|
224
|
+
/// @access public
|
|
225
|
+
@mixin grid-responsive($breakpoint-columns, $gap: $grid-gap-default, $selector: "> *", $test: false) {
|
|
226
|
+
$gap-half: math.div($gap, 2);
|
|
227
|
+
|
|
228
|
+
// ═══════════════════════════════════════
|
|
229
|
+
// FALLBACK: Flexbox (весь блок)
|
|
230
|
+
// ═══════════════════════════════════════
|
|
231
|
+
display: flex;
|
|
232
|
+
flex-wrap: wrap;
|
|
233
|
+
margin: -#{$gap-half};
|
|
234
|
+
|
|
235
|
+
#{$selector} {
|
|
236
|
+
box-sizing: border-box;
|
|
237
|
+
min-width: 0;
|
|
238
|
+
margin: $gap-half;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Flex: респонсивные колонки
|
|
242
|
+
@each $bp, $cols in $breakpoint-columns {
|
|
243
|
+
@if $bp == xs or $bp == base {
|
|
244
|
+
#{$selector} {
|
|
245
|
+
flex: 0 0 _flex-width($cols, $gap);
|
|
246
|
+
width: _flex-width($cols, $gap);
|
|
247
|
+
max-width: _flex-width($cols, $gap);
|
|
248
|
+
}
|
|
249
|
+
} @else {
|
|
250
|
+
@include breakpoints.media($bp) {
|
|
251
|
+
#{$selector} {
|
|
252
|
+
flex: 0 0 _flex-width($cols, $gap);
|
|
253
|
+
width: _flex-width($cols, $gap);
|
|
254
|
+
max-width: _flex-width($cols, $gap);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ═══════════════════════════════════════
|
|
261
|
+
// MODERN: CSS Grid (внутри @supports!)
|
|
262
|
+
// ═══════════════════════════════════════
|
|
263
|
+
@if $test != true {
|
|
264
|
+
@supports (display: grid) {
|
|
265
|
+
display: grid;
|
|
266
|
+
gap: $gap;
|
|
267
|
+
margin: 0;
|
|
268
|
+
|
|
269
|
+
// Базовые стили элементов — сбрасываем flex!
|
|
270
|
+
#{$selector} {
|
|
271
|
+
width: auto;
|
|
272
|
+
max-width: none;
|
|
273
|
+
margin: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Grid: респонсивные колонки
|
|
277
|
+
@each $bp, $cols in $breakpoint-columns {
|
|
278
|
+
@if $bp == xs or $bp == base {
|
|
279
|
+
grid-template-columns: repeat($cols, 1fr);
|
|
280
|
+
} @else {
|
|
281
|
+
@include breakpoints.media($bp) {
|
|
282
|
+
grid-template-columns: repeat($cols, 1fr);
|
|
283
|
+
|
|
284
|
+
// КЛЮЧЕВОЙ МОМЕНТ: сбрасываем flex стили ВНУТРИ каждого медиа-запроса!
|
|
285
|
+
#{$selector} {
|
|
286
|
+
width: auto;
|
|
287
|
+
max-width: none;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ─────────────────────────────────────────
|
|
297
|
+
// ГОТОВЫЕ ПРЕСЕТЫ
|
|
298
|
+
// ─────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
/// Пресет: 2 колонки (1→2)
|
|
301
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap
|
|
302
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
303
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
304
|
+
/// @require {mixin} grid-responsive
|
|
305
|
+
/// @example scss
|
|
306
|
+
/// .two-columns {
|
|
307
|
+
/// @include grid-2-cols;
|
|
308
|
+
/// }
|
|
309
|
+
/// @group grid-presets
|
|
310
|
+
/// @access public
|
|
311
|
+
@mixin grid-2-cols($gap: $grid-gap-default, $selector: "> *", $test: false) {
|
|
312
|
+
@include grid-responsive(
|
|
313
|
+
(
|
|
314
|
+
xs: 1,
|
|
315
|
+
md: 2,
|
|
316
|
+
),
|
|
317
|
+
$gap,
|
|
318
|
+
$selector,
|
|
319
|
+
$test
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/// Пресет: 3 колонки (1→2→3)
|
|
324
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap
|
|
325
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
326
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
327
|
+
/// @require {mixin} grid-responsive
|
|
328
|
+
/// @example scss
|
|
329
|
+
/// .three-columns {
|
|
330
|
+
/// @include grid-3-cols(spacing.$gap-lg);
|
|
331
|
+
/// }
|
|
332
|
+
/// @group grid-presets
|
|
333
|
+
/// @access public
|
|
334
|
+
@mixin grid-3-cols($gap: $grid-gap-default, $selector: "> *", $test: false) {
|
|
335
|
+
@include grid-responsive(
|
|
336
|
+
(
|
|
337
|
+
xs: 1,
|
|
338
|
+
sm: 2,
|
|
339
|
+
lg: 3,
|
|
340
|
+
),
|
|
341
|
+
$gap,
|
|
342
|
+
$selector,
|
|
343
|
+
$test
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/// Пресет: 4 колонки (1→2→3→4)
|
|
348
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap
|
|
349
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
350
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
351
|
+
/// @require {mixin} grid-responsive
|
|
352
|
+
/// @example scss
|
|
353
|
+
/// .four-columns {
|
|
354
|
+
/// @include grid-4-cols;
|
|
355
|
+
/// }
|
|
356
|
+
/// @group grid-presets
|
|
357
|
+
/// @access public
|
|
358
|
+
@mixin grid-4-cols($gap: $grid-gap-default, $selector: "> *", $test: false) {
|
|
359
|
+
@include grid-responsive(
|
|
360
|
+
(
|
|
361
|
+
xs: 1,
|
|
362
|
+
sm: 2,
|
|
363
|
+
lg: 3,
|
|
364
|
+
xl: 4,
|
|
365
|
+
),
|
|
366
|
+
$gap,
|
|
367
|
+
$selector,
|
|
368
|
+
$test
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/// Пресет: сетка услуг (1→2→3)
|
|
373
|
+
/// Увеличенный gap для карточек услуг
|
|
374
|
+
/// @param {Number} $gap [spacing.$gap-lg] - Gap
|
|
375
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
376
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
377
|
+
/// @require {mixin} grid-responsive
|
|
378
|
+
/// @example scss
|
|
379
|
+
/// .services__list {
|
|
380
|
+
/// @include grid-services;
|
|
381
|
+
/// }
|
|
382
|
+
/// @group grid-presets
|
|
383
|
+
/// @access public
|
|
384
|
+
@mixin grid-services($gap: spacing.$gap-lg, $selector: "> *", $test: false) {
|
|
385
|
+
@include grid-responsive(
|
|
386
|
+
(
|
|
387
|
+
xs: 1,
|
|
388
|
+
md: 2,
|
|
389
|
+
xl: 3,
|
|
390
|
+
),
|
|
391
|
+
$gap,
|
|
392
|
+
$selector,
|
|
393
|
+
$test
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/// Пресет: сетка прогресса/статистики (1→3)
|
|
398
|
+
/// @param {Number} $gap [spacing.$gap-lg] - Gap
|
|
399
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
400
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
401
|
+
/// @require {mixin} grid-responsive
|
|
402
|
+
/// @example scss
|
|
403
|
+
/// .stats__list {
|
|
404
|
+
/// @include grid-progress;
|
|
405
|
+
/// }
|
|
406
|
+
/// @group grid-presets
|
|
407
|
+
/// @access public
|
|
408
|
+
@mixin grid-progress($gap: spacing.$gap-lg, $selector: "> *", $test: false) {
|
|
409
|
+
@include grid-responsive(
|
|
410
|
+
(
|
|
411
|
+
xs: 1,
|
|
412
|
+
md: 3,
|
|
413
|
+
),
|
|
414
|
+
$gap,
|
|
415
|
+
$selector,
|
|
416
|
+
$test
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/// Пресет: сетка товаров (1→2→3→4)
|
|
421
|
+
/// @param {Number} $gap [spacing.$gap-md] - Gap
|
|
422
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
423
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
424
|
+
/// @require {mixin} grid-responsive
|
|
425
|
+
/// @example scss
|
|
426
|
+
/// .products__grid {
|
|
427
|
+
/// @include grid-products;
|
|
428
|
+
/// }
|
|
429
|
+
/// @group grid-presets
|
|
430
|
+
/// @access public
|
|
431
|
+
@mixin grid-products($gap: spacing.$gap-md, $selector: "> *", $test: false) {
|
|
432
|
+
@include grid-responsive(
|
|
433
|
+
(
|
|
434
|
+
xs: 1,
|
|
435
|
+
sm: 2,
|
|
436
|
+
lg: 3,
|
|
437
|
+
xxl: 4,
|
|
438
|
+
),
|
|
439
|
+
$gap,
|
|
440
|
+
$selector,
|
|
441
|
+
$test
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/// Пресет: галерея (2→3→4→5)
|
|
446
|
+
/// Минимальный gap, начинается с 2 колонок
|
|
447
|
+
/// @param {Number} $gap [spacing.$gap-sm] - Gap
|
|
448
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
449
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
450
|
+
/// @require {mixin} grid-responsive
|
|
451
|
+
/// @example scss
|
|
452
|
+
/// .gallery__grid {
|
|
453
|
+
/// @include grid-gallery;
|
|
454
|
+
/// }
|
|
455
|
+
/// @group grid-presets
|
|
456
|
+
/// @access public
|
|
457
|
+
@mixin grid-gallery($gap: spacing.$gap-sm, $selector: "> *", $test: false) {
|
|
458
|
+
@include grid-responsive(
|
|
459
|
+
(
|
|
460
|
+
xs: 2,
|
|
461
|
+
sm: 3,
|
|
462
|
+
lg: 4,
|
|
463
|
+
xl: 5,
|
|
464
|
+
),
|
|
465
|
+
$gap,
|
|
466
|
+
$selector,
|
|
467
|
+
$test
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ─────────────────────────────────────────
|
|
472
|
+
// GRID ITEM HELPERS
|
|
473
|
+
// ─────────────────────────────────────────
|
|
474
|
+
|
|
475
|
+
/// Растянуть элемент на N колонок
|
|
476
|
+
/// @param {Number} $span - Количество колонок
|
|
477
|
+
/// @example scss
|
|
478
|
+
/// .featured-item {
|
|
479
|
+
/// @include grid-span(2);
|
|
480
|
+
/// }
|
|
481
|
+
/// @output grid-column: span N;
|
|
482
|
+
/// @group grid-item
|
|
483
|
+
/// @access public
|
|
484
|
+
@mixin grid-span($span) {
|
|
485
|
+
grid-column: span $span;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/// Растянуть элемент на всю ширину
|
|
489
|
+
/// @example scss
|
|
490
|
+
/// .full-width-item {
|
|
491
|
+
/// @include grid-full;
|
|
492
|
+
/// }
|
|
493
|
+
/// @output grid-column: 1 / -1;
|
|
494
|
+
/// @group grid-item
|
|
495
|
+
/// @access public
|
|
496
|
+
@mixin grid-full {
|
|
497
|
+
grid-column: 1 / -1;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/// Растянуть элемент на N строк
|
|
501
|
+
/// @param {Number} $span - Количество строк
|
|
502
|
+
/// @example scss
|
|
503
|
+
/// .tall-item {
|
|
504
|
+
/// @include grid-row-span(2);
|
|
505
|
+
/// }
|
|
506
|
+
/// @output grid-row: span N;
|
|
507
|
+
/// @group grid-item
|
|
508
|
+
/// @access public
|
|
509
|
+
@mixin grid-row-span($span) {
|
|
510
|
+
grid-row: span $span;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// ─────────────────────────────────────────
|
|
514
|
+
// GRID LIMIT ITEMS
|
|
515
|
+
// ─────────────────────────────────────────
|
|
516
|
+
|
|
517
|
+
/// Ограничивает количество видимых элементов на разных брейкпоинтах
|
|
518
|
+
/// @param {Map} $limits - Карта (breakpoint: max-items)
|
|
519
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
520
|
+
/// @require {mixin} breakpoints.media
|
|
521
|
+
/// @example scss - Показать 3 на lg, 4 на xl
|
|
522
|
+
/// .features {
|
|
523
|
+
/// @include grid-limit-items((
|
|
524
|
+
/// lg: 3,
|
|
525
|
+
/// xl: 4
|
|
526
|
+
/// ));
|
|
527
|
+
/// }
|
|
528
|
+
/// @output :nth-child(n + N) { display: none } для каждого брейкпоинта
|
|
529
|
+
/// @group grid-limit
|
|
530
|
+
/// @access public
|
|
531
|
+
@mixin grid-limit-items($limits, $selector: "> *") {
|
|
532
|
+
// Сортируем брейкпоинты и создаём диапазоны
|
|
533
|
+
$breakpoint-keys: map.keys($limits);
|
|
534
|
+
$length: list.length($breakpoint-keys);
|
|
535
|
+
|
|
536
|
+
@for $i from 1 through $length {
|
|
537
|
+
$bp: list.nth($breakpoint-keys, $i);
|
|
538
|
+
$limit: map.get($limits, $bp);
|
|
539
|
+
$next-bp: null;
|
|
540
|
+
@if $i < $length {
|
|
541
|
+
$next-bp: list.nth($breakpoint-keys, $i + 1);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
@if $next-bp {
|
|
545
|
+
// Диапазон: от $bp до $next-bp
|
|
546
|
+
@include breakpoints.media($bp, min-max, $next-bp) {
|
|
547
|
+
#{$selector}:nth-child(n + #{$limit + 1}) {
|
|
548
|
+
display: none;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
} @else {
|
|
552
|
+
// Последний брейкпоинт — от $bp и выше
|
|
553
|
+
@include breakpoints.media($bp) {
|
|
554
|
+
#{$selector}:nth-child(n + #{$limit + 1}) {
|
|
555
|
+
display: none;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/// Скрыть элементы после N на конкретном брейкпоинте и выше
|
|
563
|
+
/// @param {String} $breakpoint - Брейкпоинт (lg, xl, etc.)
|
|
564
|
+
/// @param {Number} $show - Сколько показывать
|
|
565
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
566
|
+
/// @require {mixin} breakpoints.media
|
|
567
|
+
/// @example scss - Показать только 4 на lg+
|
|
568
|
+
/// .cards {
|
|
569
|
+
/// @include grid-hide-after(lg, 4);
|
|
570
|
+
/// }
|
|
571
|
+
/// @output @media (min-width) { :nth-child(n+N) { display: none } }
|
|
572
|
+
/// @group grid-limit
|
|
573
|
+
/// @access public
|
|
574
|
+
@mixin grid-hide-after($breakpoint, $show, $selector: "> *") {
|
|
575
|
+
@include breakpoints.media($breakpoint) {
|
|
576
|
+
#{$selector}:nth-child(n + #{$show + 1}) {
|
|
577
|
+
display: none;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/// Скрыть элементы после N только в диапазоне брейкпоинтов
|
|
583
|
+
/// @param {String} $from - Начальный брейкпоинт
|
|
584
|
+
/// @param {String} $to - Конечный брейкпоинт
|
|
585
|
+
/// @param {Number} $show - Сколько показывать
|
|
586
|
+
/// @param {String} $selector ["> *"] - Селектор
|
|
587
|
+
/// @require {mixin} breakpoints.media
|
|
588
|
+
/// @example scss - Показать 3 только между md и lg
|
|
589
|
+
/// .cards {
|
|
590
|
+
/// @include grid-hide-after-between(md, lg, 3);
|
|
591
|
+
/// }
|
|
592
|
+
/// @output @media (min-width) and (max-width) { ... }
|
|
593
|
+
/// @group grid-limit
|
|
594
|
+
/// @access public
|
|
595
|
+
@mixin grid-hide-after-between($from, $to, $show, $selector: "> *") {
|
|
596
|
+
@include breakpoints.media($from, min-max, $to) {
|
|
597
|
+
#{$selector}:nth-child(n + #{$show + 1}) {
|
|
598
|
+
display: none;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ─────────────────────────────────────────
|
|
604
|
+
// GRID AREAS
|
|
605
|
+
// ─────────────────────────────────────────
|
|
606
|
+
|
|
607
|
+
/// Grid с именованными областями и простым flex fallback
|
|
608
|
+
/// @param {List} $areas - Строка областей ("header header" "sidebar main")
|
|
609
|
+
/// @param {List} $columns [null] - Колонки (1fr 2fr)
|
|
610
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap
|
|
611
|
+
/// @param {Number} $cols-count [1] - Колонок для flex fallback
|
|
612
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
613
|
+
/// @example scss
|
|
614
|
+
/// .layout {
|
|
615
|
+
/// @include grid-areas(
|
|
616
|
+
/// "header header" "sidebar main" "footer footer",
|
|
617
|
+
/// 1fr 3fr,
|
|
618
|
+
/// spacing.$gap-lg,
|
|
619
|
+
/// 2
|
|
620
|
+
/// );
|
|
621
|
+
/// }
|
|
622
|
+
/// @output Flex fallback + grid-template-areas через @supports
|
|
623
|
+
/// @group grid-areas
|
|
624
|
+
/// @access public
|
|
625
|
+
@mixin grid-areas($areas, $columns: null, $gap: $grid-gap-default, $cols-count: 1, $test: false) {
|
|
626
|
+
$gap-half: math.div($gap, 2);
|
|
627
|
+
|
|
628
|
+
// FALLBACK: простой Flex
|
|
629
|
+
display: flex;
|
|
630
|
+
flex-wrap: wrap;
|
|
631
|
+
margin: -#{$gap-half};
|
|
632
|
+
|
|
633
|
+
> * {
|
|
634
|
+
box-sizing: border-box;
|
|
635
|
+
margin: $gap-half;
|
|
636
|
+
flex: 0 0 calc(#{math.percentage(math.div(1, $cols-count))} - #{$gap});
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// MODERN: CSS Grid
|
|
640
|
+
@if $test != true {
|
|
641
|
+
@supports (display: grid) {
|
|
642
|
+
display: grid;
|
|
643
|
+
gap: $gap;
|
|
644
|
+
margin: 0;
|
|
645
|
+
grid-template-areas: $areas;
|
|
646
|
+
|
|
647
|
+
@if $columns {
|
|
648
|
+
grid-template-columns: $columns;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
> * {
|
|
652
|
+
margin: 0;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/// Присвоить элементу grid-area
|
|
659
|
+
/// @param {String} $name - Имя области
|
|
660
|
+
/// @example scss
|
|
661
|
+
/// .sidebar {
|
|
662
|
+
/// @include grid-area(sidebar);
|
|
663
|
+
/// }
|
|
664
|
+
/// @output grid-area: name (только в @supports)
|
|
665
|
+
/// @group grid-areas
|
|
666
|
+
/// @access public
|
|
667
|
+
@mixin grid-area($name) {
|
|
668
|
+
@supports (display: grid) {
|
|
669
|
+
grid-area: $name;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// ─────────────────────────────────────────
|
|
674
|
+
// DISPLAY UTILITIES
|
|
675
|
+
// ─────────────────────────────────────────
|
|
676
|
+
|
|
677
|
+
/// Display: contents — элемент "исчезает", дети становятся частью родительского grid/flex
|
|
678
|
+
/// @param {String} $fallback [block] - display для старых браузеров
|
|
679
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
680
|
+
/// @example scss
|
|
681
|
+
/// .wrapper {
|
|
682
|
+
/// @include display-contents;
|
|
683
|
+
/// }
|
|
684
|
+
/// @output display: block (fallback) + display: contents (modern)
|
|
685
|
+
/// @group grid-display
|
|
686
|
+
/// @access public
|
|
687
|
+
@mixin display-contents($fallback: block, $test: false) {
|
|
688
|
+
// FALLBACK: обычный display
|
|
689
|
+
display: $fallback;
|
|
690
|
+
|
|
691
|
+
// MODERN: contents
|
|
692
|
+
@if $test != true {
|
|
693
|
+
@supports (display: contents) {
|
|
694
|
+
display: contents;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/// Display: contents только на определённом брейкпоинте и выше
|
|
700
|
+
/// @param {String} $breakpoint - Брейкпоинт (lg, xl, etc.)
|
|
701
|
+
/// @param {String} $fallback [block] - display для старых браузеров
|
|
702
|
+
/// @param {Boolean} $test [false] - Тестовый режим
|
|
703
|
+
/// @require {mixin} breakpoints.media
|
|
704
|
+
/// @example scss
|
|
705
|
+
/// .mobile-wrapper {
|
|
706
|
+
/// @include display-contents-up(lg);
|
|
707
|
+
/// }
|
|
708
|
+
/// @output display: block + @media { display: contents }
|
|
709
|
+
/// @group grid-display
|
|
710
|
+
/// @access public
|
|
711
|
+
@mixin display-contents-up($breakpoint, $fallback: block, $test: false) {
|
|
712
|
+
display: $fallback;
|
|
713
|
+
|
|
714
|
+
@if $test != true {
|
|
715
|
+
@include breakpoints.media($breakpoint) {
|
|
716
|
+
@supports (display: contents) {
|
|
717
|
+
display: contents;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// ─────────────────────────────────────────
|
|
724
|
+
// GRID EXPAND
|
|
725
|
+
// ─────────────────────────────────────────
|
|
726
|
+
|
|
727
|
+
/// Разворачивает обёртки в плоский grid
|
|
728
|
+
/// Использует display: contents для "растворения" обёрток
|
|
729
|
+
/// @param {List} $areas - Области ("address info docs contacts")
|
|
730
|
+
/// @param {List} $columns - Колонки (repeat(4, 1fr))
|
|
731
|
+
/// @param {Number} $gap [$grid-gap-default] - Gap
|
|
732
|
+
/// @example scss
|
|
733
|
+
/// .contacts-grid {
|
|
734
|
+
/// @include grid-expand(
|
|
735
|
+
/// "address info docs contacts",
|
|
736
|
+
/// repeat(4, 1fr)
|
|
737
|
+
/// );
|
|
738
|
+
/// }
|
|
739
|
+
/// @output grid layout только если contents поддерживается
|
|
740
|
+
/// @group grid-expand
|
|
741
|
+
/// @access public
|
|
742
|
+
@mixin grid-expand($areas, $columns, $gap: $grid-gap-default) {
|
|
743
|
+
@supports (display: contents) {
|
|
744
|
+
display: grid;
|
|
745
|
+
grid-template-columns: $columns;
|
|
746
|
+
grid-template-areas: $areas;
|
|
747
|
+
gap: $gap;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/// Применить display: contents к обёртке
|
|
752
|
+
/// Обёртка "исчезает", её дети становятся прямыми потомками grid
|
|
753
|
+
/// @example scss
|
|
754
|
+
/// .contact-group {
|
|
755
|
+
/// @include grid-expand-wrapper;
|
|
756
|
+
/// }
|
|
757
|
+
/// @output display: contents (только если поддерживается)
|
|
758
|
+
/// @group grid-expand
|
|
759
|
+
/// @access public
|
|
760
|
+
@mixin grid-expand-wrapper {
|
|
761
|
+
@supports (display: contents) {
|
|
762
|
+
display: contents;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/// Применить grid-area к элементу внутри "развёрнутой" обёртки
|
|
767
|
+
/// @param {String} $name - Имя области
|
|
768
|
+
/// @example scss
|
|
769
|
+
/// .contact-address {
|
|
770
|
+
/// @include grid-expand-area(address);
|
|
771
|
+
/// }
|
|
772
|
+
/// @output grid-area: name (только если contents поддерживается)
|
|
773
|
+
/// @group grid-expand
|
|
774
|
+
/// @access public
|
|
775
|
+
@mixin grid-expand-area($name) {
|
|
776
|
+
@supports (display: contents) {
|
|
777
|
+
grid-area: $name;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// // Простой grid — пресет
|
|
782
|
+
// .cards {
|
|
783
|
+
// @include grid-3-cols(spacing.$gap-lg);
|
|
784
|
+
// }
|
|
785
|
+
|
|
786
|
+
// // Кастомный респонсивный grid
|
|
787
|
+
// .products {
|
|
788
|
+
// @include grid-responsive((
|
|
789
|
+
// xs: 1,
|
|
790
|
+
// sm: 2,
|
|
791
|
+
// lg: 3,
|
|
792
|
+
// xxl: 4
|
|
793
|
+
// ));
|
|
794
|
+
// }
|
|
795
|
+
|
|
796
|
+
// // Auto-fit — сам подстраивается
|
|
797
|
+
// .features {
|
|
798
|
+
// @include grid-auto-fit(250px);
|
|
799
|
+
// }
|
|
800
|
+
|
|
801
|
+
// // Grid areas для сложных лейаутов
|
|
802
|
+
// .page-layout {
|
|
803
|
+
// @include grid-areas(
|
|
804
|
+
// "header header" "sidebar main" "footer footer",
|
|
805
|
+
// 200px 1fr
|
|
806
|
+
// );
|
|
807
|
+
|
|
808
|
+
// .header { @include grid-area(header); }
|
|
809
|
+
// .sidebar { @include grid-area(sidebar); }
|
|
810
|
+
// }
|
|
811
|
+
|
|
812
|
+
// // Ограничение элементов
|
|
813
|
+
// .news {
|
|
814
|
+
// @include grid-3-cols;
|
|
815
|
+
// @include grid-limit-items((lg: 3, xl: 6));
|
|
816
|
+
// }
|