added blur on topBar
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
/* ─────────────────────────────────────────────────────────────────────
|
||||
СТЕКЛЯННАЯ ШАПКА + ЗАТУХАНИЕ ЛЕНТЫ (Telegram Web style)
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
|
||||
Регистрация кастомного свойства: именно благодаря @property смена
|
||||
--feed-fade-height анимируется transition'ом. В браузерах без поддержки
|
||||
@property значение просто меняется мгновенно (graceful degradation).
|
||||
*/
|
||||
@property --feed-fade-height {
|
||||
syntax: '<length>';
|
||||
inherits: false;
|
||||
initial-value: 48px;
|
||||
}
|
||||
|
||||
/* ── App Shell (Instagram-style) ── */
|
||||
.f-app {
|
||||
display: flex; height: 100vh; height: 100dvh;
|
||||
@@ -19,17 +33,46 @@
|
||||
}
|
||||
|
||||
/* ── Topbar (telegram-style; mobile only; desktop uses the nav sidebar) ──
|
||||
Фон отсутствует полностью: стеклянными выглядят только сами кнопки. */
|
||||
«Стекло»: полупрозрачный фон темы + мягкий blur по содержимому под шапкой.
|
||||
blur/saturate явно умеренные — сильно агрессивное размытие даёт
|
||||
пересвеченное «стекло» (blur 12px + saturate ~135%). */
|
||||
.f-topbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
padding-top: calc(8px + env(safe-area-inset-top));
|
||||
/* Без backdrop-filter: blur имеет жёсткую границу по кромке прямоугольника,
|
||||
которую маской не убрать. Плавность даёт только сквозной альфа-градиент,
|
||||
сходящийся к 0 уже к низу бара. */
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(var(--bg-rgb), 0.14) 0%,
|
||||
rgba(var(--bg-rgb), 0.07) 55%,
|
||||
rgba(var(--bg-rgb), 0.05) 100%
|
||||
);
|
||||
transition: transform 0.25s ease, background-color 0.25s ease;
|
||||
}
|
||||
|
||||
/* Продолжение того же сквозного градиента ниже бара: цвет уходит в 0,
|
||||
резкой границы нет, «плашки» не видно вообще. */
|
||||
.f-topbar::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 100%;
|
||||
height: 64px;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(var(--bg-rgb), 0.05) 0%,
|
||||
rgba(var(--bg-rgb), 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Кнопка-логотип по центру: wordmark «Находка» в округлой стеклянной капсуле */
|
||||
@@ -206,18 +249,22 @@
|
||||
.f-topbar-dropdown-wrap {
|
||||
position: relative;
|
||||
}
|
||||
/* В ленте шапка липнет к верху скроллера: контент прокручивается под ней
|
||||
и «замыливается» через backdrop-filter на .f-topbar */
|
||||
.f-feed > .f-topbar-dropdown-wrap {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
margin: -20px -16px 0;
|
||||
.f-topbar-dropdown-wrap .f-topbar.f-topbar-hidden {
|
||||
/* Плавное скрытие шапки при скролле вниз (translateY вверх, за кромку .f-feed).
|
||||
Висим на самом .f-topbar, а НЕ на обёртке: transform на обёртке создал бы
|
||||
containing block для position:fixed оверлея дропдауна и сломал бы клик вне. */
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.f-feed > .f-topbar-dropdown-wrap {
|
||||
margin: -10px -10px 0;
|
||||
}
|
||||
/* В ленте шапка лежит ПОВЕРХ маскированного скролл-контейнера (.f-feed-scroll):
|
||||
по z-index она выше «слоя затухания», но ниже, чем сам контент не бывает
|
||||
никогда — жёстко прижата к верху .f-feed. */
|
||||
.f-feed > .f-topbar-dropdown-wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.f-topbar-dropdown-overlay {
|
||||
@@ -577,14 +624,45 @@
|
||||
/* ── Feed Wrap + Scroll ── */
|
||||
.f-wrap { display: flex; flex: 1; overflow: hidden; min-height: 0; }
|
||||
|
||||
/* Внешний контейнер ленты: не скроллится, лишь позиционирует слои.
|
||||
Сверху — стеклянная шапка (абсолютный слой), под ней — маскированный
|
||||
скролл-список; такой порядок даёт нужную иерархию z-index. */
|
||||
.f-feed {
|
||||
flex: 1; overflow-y: scroll; overflow-x: hidden; overscroll-behavior: contain; min-height: 0;
|
||||
padding: 20px 16px; display: flex; flex-direction: column; gap: 16px;
|
||||
width: 100%; max-width: 660px; margin: 0 auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
max-width: 660px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.f-feed::-webkit-scrollbar { width: 4px; }
|
||||
.f-feed::-webkit-scrollbar-track { background: transparent; }
|
||||
.f-feed::-webkit-scrollbar-thumb { background: var(--muted2); border-radius: 2px; }
|
||||
|
||||
/* ── Слой затухания ленты ──
|
||||
mask-image на самом контейнере списка (НЕ blur, НЕ opacity карточек):
|
||||
верхние элементы, доезжающие до кромки под FeedTopBar, «растворяются».
|
||||
Маска якорена к border-box скролл-контейнера, т.е. НЕ уезжает вместе
|
||||
с карточками — зона затухания всегда под шапкой. Высота зоны задаётся
|
||||
--feed-fade-height (управляется из React/ResizeObserver) и через
|
||||
@property + transition анимируется при изменении.
|
||||
padding-top синхронизирован с этой же переменной, чтобы первая карточка
|
||||
в состоянии покоя не проваливалась под шапку. */
|
||||
.f-feed-scroll {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: contain;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: calc(var(--feed-fade-height, 48px) + 20px) 16px 20px;
|
||||
-webkit-mask-image: linear-gradient(to bottom, transparent 0, black var(--feed-fade-height, 48px));
|
||||
mask-image: linear-gradient(to bottom, transparent 0, black var(--feed-fade-height, 48px));
|
||||
transition: --feed-fade-height 0.2s ease;
|
||||
}
|
||||
.f-feed-scroll::-webkit-scrollbar { width: 4px; }
|
||||
.f-feed-scroll::-webkit-scrollbar-track { background: transparent; }
|
||||
.f-feed-scroll::-webkit-scrollbar-thumb { background: var(--muted2); border-radius: 2px; }
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.f-main-feed .f-topbar {
|
||||
@@ -611,8 +689,8 @@
|
||||
bottom: calc(84px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.f-feed {
|
||||
padding: 10px;
|
||||
.f-feed-scroll {
|
||||
padding: calc(var(--feed-fade-height, 48px) + 10px) 10px calc(150px + env(safe-area-inset-bottom));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
@@ -645,11 +723,6 @@
|
||||
margin-top: 4px; border-radius: 999px;
|
||||
}
|
||||
.f-topbar-dropdown-item { padding: 7px 13px; font-size: 0.8rem; }
|
||||
|
||||
/* Нижняя панель fixed — освобождаем место в конце ленты */
|
||||
.f-feed {
|
||||
padding-bottom: calc(150px + env(safe-area-inset-bottom));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
Reference in New Issue
Block a user