SCSS система
Flute CMS использует SCSS для стилизации. SCSS компилируется автоматически, поддерживает миксины и utility-классы.
Структура SCSS файлов
Главный файл app.scss
Создайте assets/sass/app.scss:
// 1. Переменные темы
@import 'theme/variables';
// 2. Компоненты (если переопределяете)
@import 'components/buttons';
@import 'components/cards';
// 3. Страницы
@import 'pages/home';
// 4. Свои стили
.my-custom-element {
// ...
}Рекомендуемая структура
- app.scss
Готовые миксины
Адаптивность (@media)
.element {
padding: var(--space-xl);
font-size: var(--h2);
@include media(tablet) {
padding: var(--space-lg);
font-size: var(--h3);
}
@include media(mobile) {
padding: var(--space-md);
font-size: var(--h4);
}
}Брейкпоинты:
| Название | Ширина | Описание |
|---|---|---|
mobile | ≤768px | Телефоны |
tablet | ≤1024px | Планшеты |
desktop | >1024px | Десктоп |
Анимации (@transition)
.element {
@include transition(all);
&:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-large);
}
}
// Только определенные свойства
.element {
@include transition(background, color);
}Готовые utility-классы
Flexbox
<!-- Базовый flex -->
<div class="flex">...</div>
<!-- Центрирование -->
<div class="flex-center">...</div>
<!-- Space-between -->
<div class="flex-between">...</div>
<!-- Колонка -->
<div class="flex-column">...</div>
<!-- С gap -->
<div class="flex gap-sm">...</div>
<div class="flex gap-md">...</div>
<div class="flex gap-lg">...</div>Что они делают:
.flex { display: flex; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.flex-column { display: flex; flex-direction: column; }
.gap-sm { gap: var(--space-sm); } // 8px
.gap-md { gap: var(--space-md); } // 16px
.gap-lg { gap: var(--space-lg); } // 24pxGrid
<div class="grid grid-2">...</div> <!-- 2 колонки -->
<div class="grid grid-3">...</div> <!-- 3 колонки -->
<div class="grid grid-4">...</div> <!-- 4 колонки -->Текст
<p class="text-center">Центрированный</p>
<p class="text-left">По левому краю</p>
<p class="text-right">По правому краю</p>
<p class="text-muted">Приглушенный цвет</p>
<p class="text-accent">Цвет акцента</p>
<p class="text-error">Красный</p>
<p class="text-success">Зеленый</p>
<p class="text-warning">Желтый</p>
<p class="font-bold">Жирный</p>
<p class="font-medium">Средний</p>Отступы (margin/padding)
<!-- Margin -->
<div class="mt-1">margin-top: 4px</div>
<div class="mt-2">margin-top: 8px</div>
<div class="mt-3">margin-top: 16px</div>
<div class="mt-4">margin-top: 24px</div>
<div class="mt-5">margin-top: 32px</div>
<div class="mb-3">margin-bottom: 16px</div>
<div class="ml-3">margin-left: 16px</div>
<div class="mr-3">margin-right: 16px</div>
<div class="mx-3">margin-left + right: 16px</div>
<div class="my-3">margin-top + bottom: 16px</div>
<!-- Padding -->
<div class="p-3">padding: 16px</div>
<div class="px-3">padding-left + right: 16px</div>
<div class="py-3">padding-top + bottom: 16px</div>
<div class="pt-3">padding-top: 16px</div>Размеры
<div class="w-100">width: 100%</div>
<div class="h-100">height: 100%</div>Скрытие
<div class="hidden">display: none</div>
<div class="visible">display: block</div>Переопределение стандартных компонентов
Кнопки
// assets/sass/components/_buttons.scss
.btn {
// Pill-кнопки
border-radius: 50px;
// Uppercase
text-transform: uppercase;
font-weight: 600;
letter-spacing: 0.025em;
// Другой padding
padding: var(--space-sm) var(--space-xl);
}
// Gradient кнопка
.btn-accent {
background: linear-gradient(135deg, var(--accent), var(--accent-600));
&:hover {
background: linear-gradient(135deg, var(--accent-600), var(--accent-700));
}
}
// Outline с эффектом
.btn-outline-accent {
background: transparent;
border: 2px solid var(--accent);
color: var(--accent);
&:hover {
background: var(--accent);
color: white;
}
}Карточки
// assets/sass/components/_cards.scss
.card {
background: var(--secondary);
border: none;
border-radius: var(--border1);
box-shadow: var(--shadow-medium);
overflow: hidden;
@include transition(all);
&:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-large);
}
}
.card-header {
padding: var(--space-lg);
border-bottom: 1px solid var(--transp-1);
}
.card-body {
padding: var(--space-lg);
}
.card-footer {
padding: var(--space-md) var(--space-lg);
background: var(--third);
border-top: 1px solid var(--transp-1);
}Формы
// assets/sass/components/_forms.scss
.input {
width: 100%;
padding: var(--space-sm) var(--space-md);
background: var(--secondary);
border: 1px solid var(--transp-2);
border-radius: var(--border05);
font-size: var(--p);
color: var(--text);
@include transition(all);
&::placeholder {
color: var(--text-400);
}
&:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-100);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
// Textarea
textarea.input {
min-height: 120px;
resize: vertical;
}
// Label
.form__label {
display: block;
margin-bottom: var(--space-xs);
font-weight: 500;
font-size: var(--small);
color: var(--text);
}
// Required indicator
.form__label-required::after {
content: ' *';
color: var(--error);
}
// Error state
.input.has-error {
border-color: var(--error);
&:focus {
box-shadow: 0 0 0 3px var(--error-100);
}
}Header
// assets/sass/layouts/_header.scss
.navbar {
position: sticky;
top: 0;
z-index: 100;
background: var(--blurred-background);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--transp-1);
&__content {
display: flex;
align-items: center;
justify-content: space-between;
height: 64px;
padding: 0 var(--space-lg);
}
&__logo {
img {
height: 32px;
width: auto;
}
}
&__items {
display: flex;
align-items: center;
gap: var(--space-xs);
}
&__items-item {
padding: var(--space-xs) var(--space-sm);
border-radius: var(--border05);
font-size: var(--p);
font-weight: 500;
color: var(--text-muted);
@include transition(all);
&:hover, &.active {
color: var(--text);
background: var(--transp-1);
}
}
}Создание своих компонентов
Пример: Feature Card
// assets/sass/components/_feature-card.scss
.feature-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: var(--space-xl);
background: var(--secondary);
border-radius: var(--border1);
@include transition(all);
&:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-medium);
}
&__icon {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
margin-bottom: var(--space-md);
background: var(--accent-100);
border-radius: var(--border1);
color: var(--accent);
svg {
width: 32px;
height: 32px;
}
}
&__title {
margin-bottom: var(--space-sm);
font-size: var(--h4);
font-weight: 600;
}
&__description {
color: var(--text-muted);
font-size: var(--small);
line-height: var(--line-height);
}
}Подключение в app.scss
@import 'theme/variables';
@import 'components/feature-card';BEM методология
Рекомендуется использовать BEM для именования классов:
// Блок
.card { }
// Элемент
.card__header { }
.card__body { }
.card__footer { }
// Модификатор
.card--featured { }
.card--compact { }<div class="card card--featured">
<div class="card__header">...</div>
<div class="card__body">...</div>
</div>Sass переменные (локальные)
Для удобства можно использовать Sass-переменные внутри компонентов:
.my-component {
$padding: var(--space-lg);
$border-radius: var(--border1);
padding: $padding;
border-radius: $border-radius;
&__header {
padding: $padding;
}
}