diff --git a/package-lock.json b/package-lock.json index ec0c7c27..2222996b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,7 +4,6 @@ "requires": true, "packages": { "": { - "name": "platform", "license": "MIT + CC BY-NC-SA 4.0", "dependencies": { "@11ty/eleventy-plugin-vite": "^4.0.0", @@ -5197,9 +5196,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001571", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz", - "integrity": "sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ==", + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", "funding": [ { "type": "opencollective", diff --git a/src/includes/blocks/header.njk b/src/includes/blocks/header.njk index b13cf4fa..983d6dfa 100644 --- a/src/includes/blocks/header.njk +++ b/src/includes/blocks/header.njk @@ -1,91 +1,137 @@ {% from "blocks/logo.njk" import logo %} -{% macro divider(isLarge) %} - +{% macro devider() %} + + {% endmacro %} -{% macro header(pageCategoryId, category, title, link, isLogoContrastColor, hasAccentColor, isMainPage = false, isCategoryVisible = false, isLogoImageHidden = false) %} +{% macro header( + pageCategoryId, + category, + title, + link, + isLogoContrastColor, + hasAccentColor, + isMainPage=false, + isSearchPage=false, + isCategoryVisible=false, + isLogoImageHidden=false) +%} {% set articleIndexes = collections.articleIndexes %} + + {% include "blocks/skip-link.njk" %} + - + - {{ logo(isLink=not isMainPage, isContrastColor=isLogoContrastColor, isImageHidden=isLogoImageHidden, letters=logoLetters) }} - {% if not isMainPage %}{{ divider() }}{% endif %} + {{ logo( + isLink=not isMainPage, + isContrastColor=isLogoContrastColor, + isImageHidden=isLogoImageHidden, + letters=logoLetters) + }} + {{ devider() }} {% if category %} {% if title %} - + {{ category }} - {{ divider() }} + {{ devider() }} {% else %} - + {{ category }} {% endif %} {% endif %} - - {% if title %} - - - {{ title | descriptionMarkdown | safe }} - - - {% endif %} - - - Открыть меню - - / - - - - - - - - - + {% include "blocks/search.njk" %} - - - {{ logo( - isLink=not isMainPage - ) }} - {{ divider(isLarge=true) }} - + {% if (not isMainPage) and (not isSearchPage) %} + + + Клавиша / + + + esc + - {% include "blocks/search.njk" %} - {% include "blocks/nav-list.njk" %} + + + Открыть меню + + + + + + - {% if not isMainPage %} - - - Закрыть меню - - esc - - + + Закрыть меню + + {% endif %} + + {% if isSearchPage %} + + + Очистить + + + + + + + + {% endif %} + + {% if not isSearchPage %} + + {% include "blocks/nav-list.njk" %} + + {% endif %} {% endmacro %} diff --git a/src/includes/blocks/linked-article.njk b/src/includes/blocks/linked-article.njk index 2c7942f5..d8da329f 100644 --- a/src/includes/blocks/linked-article.njk +++ b/src/includes/blocks/linked-article.njk @@ -1,7 +1,10 @@ {% macro linkedArticle(article, type = 'previous') %} {% set icon = '←' if type === 'previous' else '→' %} - + {{ icon }} diff --git a/src/includes/blocks/logo.njk b/src/includes/blocks/logo.njk index efe79c9b..c4739fda 100644 --- a/src/includes/blocks/logo.njk +++ b/src/includes/blocks/logo.njk @@ -1,4 +1,10 @@ -{% macro logo(isLink, isContrastColor, class, letters, isImageHidden=false) %} +{% macro logo( + isLink, + isContrastColor, + class, + letters, + isImageHidden = false) +%} {% set logoWrapper = linkLogo if isLink else simpleLogo %} {% set tag = 'a' if isLink else 'div' %} {% set attrs = 'href=/' if isLink %} @@ -17,15 +23,21 @@ <{{tag}} class="{{ classes }}" {{ attrs }}> {% if (not isImageHidden) %} - - + + {{ letters | safe }} - - + + UˇᴥˇU - - + + {% endif %} - Дока + + Дока + {{tag}}> {% endmacro %} diff --git a/src/includes/blocks/nav-list.njk b/src/includes/blocks/nav-list.njk index 61e8446a..72102c34 100644 --- a/src/includes/blocks/nav-list.njk +++ b/src/includes/blocks/nav-list.njk @@ -1,4 +1,4 @@ - + {% for sectionIndex in articleIndexes %} diff --git a/src/includes/blocks/search-category.njk b/src/includes/blocks/search-category.njk index 1e9eadfc..58868c0a 100644 --- a/src/includes/blocks/search-category.njk +++ b/src/includes/blocks/search-category.njk @@ -3,7 +3,7 @@ Фильтровать по: {% for category in collections.articleIndexes %} - + {{ category.data.name }} diff --git a/src/includes/blocks/search.njk b/src/includes/blocks/search.njk index 1f03c309..df93c41f 100644 --- a/src/includes/blocks/search.njk +++ b/src/includes/blocks/search.njk @@ -1,10 +1,37 @@ - + - Поиск - + + Поиск + + - / - ↲ + {% if isMainPage %} + + Клавиша / + + {% endif %} + + + Enter + @@ -16,5 +43,4 @@ Расширенный поиск - diff --git a/src/includes/blocks/skip-link.njk b/src/includes/blocks/skip-link.njk new file mode 100644 index 00000000..5cc37224 --- /dev/null +++ b/src/includes/blocks/skip-link.njk @@ -0,0 +1,3 @@ + + К контенту + diff --git a/src/includes/contributors.njk b/src/includes/contributors.njk index 6d6774c9..b020a4f9 100644 --- a/src/includes/contributors.njk +++ b/src/includes/contributors.njk @@ -11,7 +11,7 @@ {% macro personsList(list, personType, maxPersons = 3) %} {% set totalPersonsCount = list.length %} {% set extraPersonsCount = totalPersonsCount - maxPersons %} - {% set divider = "," %} + {% set devider = "," %} @@ -24,7 +24,7 @@ > {{ person(name=personItem.data.name, url='/people/' + personItem.fileSlug + '/') }} {% if not loop.last %} - {{ divider }} + {{ devider }} {% endif %} {% endfor %} diff --git a/src/scripts/modules/article-nav.js b/src/scripts/modules/article-nav.js index 85b730be..1c656ab3 100644 --- a/src/scripts/modules/article-nav.js +++ b/src/scripts/modules/article-nav.js @@ -5,19 +5,14 @@ function init() { return } - const button = nav.querySelector('.article-nav__button') - const content = nav.querySelector('.article-nav__content') + const button = nav.querySelector('.toggle-button') button.addEventListener('click', () => { nav.classList.toggle('article-nav--open') - }) - - content.addEventListener('click', (event) => { - const link = event.target.closest('a') - if (link) { - nav.classList.remove('article-nav--open') - } + let isExpanded = button.getAttribute('aria-expanded') + isExpanded = isExpanded === 'true' ? 'false' : 'true' + button.setAttribute('aria-expanded', isExpanded) }) } diff --git a/src/scripts/modules/cookie-notification.js b/src/scripts/modules/cookie-notification.js index 4ba6e89c..f8087596 100644 --- a/src/scripts/modules/cookie-notification.js +++ b/src/scripts/modules/cookie-notification.js @@ -26,7 +26,7 @@ function init() { banner.hidden = true localStorage.setItem(storageKey, true) }, - { once: true } + { once: true }, ) } diff --git a/src/scripts/modules/header.js b/src/scripts/modules/header.js index 6d6c94de..c0b98afe 100644 --- a/src/scripts/modules/header.js +++ b/src/scripts/modules/header.js @@ -3,22 +3,19 @@ import debounce from '../libs/debounce.js' import BaseComponent from '../core/base-component.js' const headerActiveClass = 'header--open' -const headerAnimationName = 'fixedHeaderAnimation' class Header extends BaseComponent { constructor({ rootElement }) { super() - /** @type {Object} */ this.refs = { rootElement, input: rootElement.querySelector('.search__input'), - toggleButtons: rootElement.querySelectorAll('.menu-toggle'), + headerContent: rootElement.querySelector('.header__controls'), + toggleButton: rootElement.querySelector('.header-button'), } this.state = { - headerHeight: null, - fixedHeaderHeight: null, lastScroll: 0, getScrollThreshold: window.innerHeight, } @@ -26,20 +23,20 @@ class Header extends BaseComponent { const scrollThresholdConditions = [ { condition: () => !!document.querySelector('.article'), - getter: () => this.state.headerHeight + document.querySelector('.article__header').offsetHeight, + getter: () => document.querySelector('.article__header'), }, { condition: () => !!document.querySelector('.index-block'), getter: () => { const additionalHeight = window.matchMedia('(width >= 1366px)') ? 0 - : document.querySelector('.index-block__header').offsetHeight - return this.state.headerHeight + additionalHeight + : document.querySelector('.index-block__header') + return additionalHeight }, }, { condition: () => !!document.querySelector('.standalone-page'), - getter: () => this.state.headerHeight + document.querySelector('.standalone-page__header').offsetHeight, + getter: () => document.querySelector('.standalone-page__header'), }, { condition: () => true, @@ -54,195 +51,167 @@ class Header extends BaseComponent { } } - ;['openOnKeyUp', 'closeOnKeyUp', 'closeOnClickOutSide', 'openMenu', 'closeMenu', 'fixHeader', 'checkFixed'].forEach( - (method) => { - this[method] = this[method].bind(this) - } - ) + ;[ + 'enter', + 'openOnKeyUp', + 'closeOnKeyUp', + 'closeOnClickOutside', + 'closeOnFocusout', + 'openMenu', + 'closeMenu', + 'stickyHeader', + 'checkSticky', + ].forEach((method) => { + this[method] = this[method].bind(this) + }) const resizeCallback = () => { - this.calculateHeaderHeight() this.calculateScrollThreshold() } const onResize = debounce(resizeCallback, 200) + this.state.lastFocusedElement = document.activeElement + window.addEventListener('resize', onResize) window.addEventListener('orientationchange', onResize) resizeCallback() - if (this.isClosableHeader) { - this.refs.toggleButtons.forEach((button) => { - button.addEventListener('click', () => { - this.isMenuOpen ? this.closeMenu() : this.openMenu() - }) + if (this.isSticky) { + this.refs.toggleButton.addEventListener('click', () => { + this.isMenuOpen ? this.closeMenu() : this.openMenu() }) document.addEventListener('keyup', this.openOnKeyUp) + window.addEventListener('scroll', throttle(this.checkSticky, { leading: false }), { passive: true }) - window.addEventListener('scroll', throttle(this.checkFixed, 250, { leading: false }), { passive: true }) - this.checkFixed() + this.checkSticky() } - } - get isFixed() { - return this.refs.rootElement.classList.contains('header--fixed') + if (this.isMainPage) { + document.addEventListener('keyup', (event) => { + if (event.code === 'Slash' || event.code === 'NumpadDivide') { + queueMicrotask(() => { + this.enter() + }) + } + }) + } } - get isMainPage() { - return this.refs.rootElement.classList.contains('header--main') + get isSticky() { + return this.refs.rootElement.classList.contains('header--sticky') } - get isClosableHeader() { - const header = this.refs.rootElement - - return [!header.classList.contains('header--static'), !header.classList.contains('search-page__header')].every( - Boolean - ) + get isMainPage() { + return window.location.pathname === '/' } get isMenuOpen() { return this.refs.rootElement.classList.contains(headerActiveClass) } - calculateHeaderHeight() { - const header = this.refs.rootElement - const state = this.state - - if (this.isFixed) { - state.fixedHeaderHeight = header.offsetHeight - header.classList.remove('header--fixed') - state.headerHeight = header.offsetHeight - header.classList.add('header--fixed') - } else { - state.headerHeight = header.offsetHeight - header.classList.add('header--fixed') - state.fixedHeaderHeight = header.offsetHeight - header.classList.remove('header--fixed') - } - - document.documentElement.style.setProperty('--fixed-header-height', state.fixedHeaderHeight) - document.documentElement.style.setProperty('--not-fixed-header-height', state.headerHeight) - } - calculateScrollThreshold() { this.scrollThreshold = this.getScrollThreshold() } + /* события для закрытия/открытия дропдауна с разделами */ + enter() { + this.refs.input?.focus() + } + openOnKeyUp(event) { - if (event.code === 'Slash') { + if (event.code === 'Slash' || event.code === 'NumpadDivide') { this.openMenu() + this.refs.input.focus() } } closeOnKeyUp(event) { - if (event.code === 'Escape' && !this.isMainPage) { + if (event.code === 'Escape') { + this.closeMenu() + } + } + + closeOnFocusout(event) { + const cookieBanner = document.querySelector('.cookie-notification') + const subscriptionBanner = document.querySelector('.subscribe-popup') + if ( + event.relatedTarget && + !this.refs.rootElement.contains(event.relatedTarget) && + !cookieBanner.contains(event.relatedTarget) && + !subscriptionBanner.contains(event.relatedTarget) + ) { this.closeMenu() } } - closeOnClickOutSide(event) { - if (!event.target.closest('.header__inner') && !this.isMainPage) { + closeOnClickOutside(event) { + const cookieBanner = document.querySelector('.cookie-notification') + const subscriptionBanner = document.querySelector('.subscribe-popup') + if ( + !this.refs.rootElement.contains(event.target) && + !cookieBanner.contains(event.target) && + !subscriptionBanner.contains(event.target) + ) { this.closeMenu() } } openMenu() { - this.refs.rootElement.classList.add(headerActiveClass) + const { rootElement, toggleButton } = this.refs + + rootElement.classList.add(headerActiveClass) + toggleButton.setAttribute('aria-expanded', 'true') + document.removeEventListener('keyup', this.openOnKeyUp) document.addEventListener('keyup', this.closeOnKeyUp) - document.addEventListener('click', this.closeOnClickOutSide) + rootElement.addEventListener('focusout', this.closeOnFocusout) + document.addEventListener('click', this.closeOnClickOutside) } closeMenu() { - const { rootElement } = this.refs + const { rootElement, toggleButton } = this.refs rootElement.classList.remove(headerActiveClass) + toggleButton.setAttribute('aria-expanded', 'false') + document.removeEventListener('keyup', this.closeOnKeyUp) - document.removeEventListener('click', this.closeOnClickOutSide) + document.removeEventListener('focusout', this.closeOnFocusout) + document.removeEventListener('click', this.closeOnClickOutside) document.addEventListener('keyup', this.openOnKeyUp) this.emit('menu.close') } - // методы для плавного появления/скрытия шапки - showHeader() { - const { rootElement: header } = this.refs - const classes = ['header--animating', 'header--fixed-show'] - - header.addEventListener( - 'animationend', - (event) => { - if (event.animationName !== headerAnimationName) { - return - } - header.classList.remove(...classes) - }, - { once: true } - ) - - this.fixHeader(true) - header.classList.add(...classes) - this.emit('fixed') + /* отслеживаем скролл, устанавливаем флаг для хедера */ + stickyHeader(flag) { + this.refs.headerContent.classList.toggle('header__controls--shrink', flag) + document.documentElement.style.setProperty('--is-header-sticky', Number(flag)) } - hideHeader() { - const { rootElement: header } = this.refs - const classes = ['header--animating', 'header--fixed-hide'] - - header.addEventListener( - 'animationend', - (event) => { - if (event.animationName !== headerAnimationName) { - return - } - this.fixHeader(false) - header.classList.remove(...classes) - }, - { once: true } - ) - - header.classList.add(...classes) - this.emit('unfixed') - } - - fixHeader(flag) { - this.refs.rootElement.classList.toggle('header--fixed', flag) - document.documentElement.style.setProperty('--is-header-fixed', Number(flag)) - } - - checkFixed() { + checkSticky() { const { lastScroll } = this.state const currentScroll = window.scrollY const isScrollingDown = currentScroll > lastScroll const isHeaderOnTop = currentScroll === 0 - const minimumScrollDistance = 180 this.state.lastScroll = currentScroll if (isHeaderOnTop) { - if (this.isFixed) { - this.fixHeader(false) - this.emit('unfixed') + if (this.isSticky) { + this.stickyHeader(false) + this.emit('unsticky') } return } - if (currentScroll <= this.scrollThreshold) { - if (this.isFixed) { - this.hideHeader() + if (isScrollingDown || currentScroll <= this.scrollThreshold) { + if (this.isSticky) { + this.stickyHeader(true) + this.emit('sticky') } return } - - if (isScrollingDown) { - if (this.isFixed) { - this.hideHeader() - } - } else { - if (!this.isFixed && !this.isMainPage && lastScroll - currentScroll >= minimumScrollDistance) { - this.showHeader() - } - } } } diff --git a/src/scripts/modules/logo.js b/src/scripts/modules/logo.js index fe67d6dd..ae5f1c75 100644 --- a/src/scripts/modules/logo.js +++ b/src/scripts/modules/logo.js @@ -7,8 +7,7 @@ class Logo { } constructor() { - // в шапке может быть два логотипа, поэтому берём последний - const rootElement = Array.from(document.querySelectorAll('.logo')).pop() + const rootElement = document.querySelector('.logo') this.refs = { rootElement, @@ -39,14 +38,12 @@ class Logo { endAnimation() { const isSearchPage = window.location.pathname.indexOf('/search/') > -1 - let logoImage + const logoImage = document.querySelector('.logo__image') let firstResultColor if (isSearchPage) { - logoImage = document.querySelector('.logo__image') firstResultColor = document?.querySelector('.search-hit')?.getAttribute('style') } else { - logoImage = document.querySelectorAll('.logo__image')[1] firstResultColor = document?.querySelector('.suggestion-list__item')?.getAttribute('style') } @@ -65,7 +62,7 @@ class Logo { this._isAnimation = false this.refs.image.classList.remove(Logo.constants.animationStateClass) }, - { once: true } + { once: true }, ) } } diff --git a/src/scripts/modules/quick-search.js b/src/scripts/modules/quick-search.js index 0f9ba9d6..f67bcca2 100644 --- a/src/scripts/modules/quick-search.js +++ b/src/scripts/modules/quick-search.js @@ -24,6 +24,7 @@ class QuickSearch extends BaseComponent { this.refs = { rootElement, input: rootElement.querySelector('.search__input'), + fullLink: rootElement.querySelector('.search__full-link'), suggestionContainer: rootElement.querySelector('.search__suggestion'), suggestionContent: rootElement.querySelector('.search__suggestion-content'), suggestionList: rootElement.querySelector('.suggestion-list'), @@ -33,7 +34,6 @@ class QuickSearch extends BaseComponent { highlightedIndex: -1, } ;[ - 'enter', 'exit', 'openSuggestion', 'closeSuggestion', @@ -57,25 +57,6 @@ class QuickSearch extends BaseComponent { this.refs.input.addEventListener('input', this.onSearch) this.refs.input.addEventListener('focus', onFocus, true) this.refs.input.addEventListener('blur', onBlur, true) - - document.addEventListener('keydown', (event) => { - // Firefox при нажатии Slash открывает свой поиск по странице - if (event.code === 'Slash' && document.activeElement !== this.refs.input) { - event.preventDefault() - } - }) - - document.addEventListener('keyup', (event) => { - if (event.code === 'Slash') { - queueMicrotask(() => { - this.enter() - }) - } - }) - } - - enter() { - this.refs.input?.focus() } exit() { @@ -125,13 +106,14 @@ class QuickSearch extends BaseComponent { closeSuggestionOnOutSideClick(event) { const { rootElement } = this.refs - if (!rootElement.contains(event.target)) { + if (!rootElement.contains(event.target) && this.isSuggestionOpen) { this.closeSuggestion() } } onSearch(event) { this.emit('search', event.target.value) + this.refs.fullLink.href = `/search/?query=${this.refs.input.value}` } onCursorChange(event) { @@ -219,7 +201,7 @@ class QuickSearch extends BaseComponent { .map((hitObject) => { const title = hitObject.originalTitle.replace( /`(.*?)`/g, - '$1' + '$1', ) return ` diff --git a/src/scripts/modules/search.js b/src/scripts/modules/search.js index 2dfe2486..c0bf355a 100644 --- a/src/scripts/modules/search.js +++ b/src/scripts/modules/search.js @@ -4,17 +4,9 @@ import BaseComponent from '../core/base-component.js' import { MIN_SEARCH_SYMBOLS, SYMBOL_LIMIT, SEARCHABLE_SHORT_WORDS, processHits } from '../core/search-commons.js' import logo from '../modules/logo.js' -function onFocus() { - logo.setFocusOnElement() -} - -function onBlur() { - logo.unsetFocusOnElement() -} - function setLiveRegion(isLiveRegion, element) { if (isLiveRegion) { - element.setAttribute('aria-live', 'assertive') + element.setAttribute('aria-live', 'polite') element.setAttribute('aria-atomic', 'true') } else { element.removeAttribute('aria-live') @@ -35,7 +27,7 @@ class Filter extends BaseComponent { }) form.addEventListener('reset', () => { - // событие reset срабатывает перед тем, как поля очистятся + /* событие reset срабатывает перед тем, как поля очистятся */ setTimeout(() => { this.emit('reset', this.state) }) @@ -126,7 +118,7 @@ class SearchResultOutput extends BaseComponent { const editIcon = SearchResultOutput.isPlaceholder(hitObject) ? SearchResultOutput.templates.placeholderIcon : '' const title = SearchResultOutput.replaceBackticks( hitObject.title.replaceAll('', ''), - SearchResultOutput.templates.titleCode + SearchResultOutput.templates.titleCode, ) const summary = hitObject.summary .slice(0, SearchResultOutput.matchedItems) @@ -157,7 +149,7 @@ class SearchResultOutput extends BaseComponent { ${SearchResultOutput.templates.hit(hitObject)} - ` + `, ) .join('')} @@ -215,7 +207,7 @@ function init() { element: searchHits, }) - // преобразует состояние фильтров в понятный серверу формат + /* преобразует состояние фильтров в понятный серверу формат */ function prepareFilters(filtersState) { const result = [ [...filtersState.getAll('category')].map((v) => { @@ -229,7 +221,7 @@ function init() { return result } - // сериализует состояние фильтров в формат Search Params + /* сериализует состояние фильтров в формат Search Params */ function filtersToSearchParams(filtersState, fallbackPath) { let searchString = new URLSearchParams(filtersState).toString() searchString = searchString ? '?' + searchString : fallbackPath @@ -273,8 +265,6 @@ function init() { const debouncedOnFilterChange = debounce(onFilterChange, 150) function assignSearchField() { - searchField.addEventListener('focus', onFocus, true) - searchField.addEventListener('blur', onBlur, true) searchField.focus() searchField.addEventListener('input', () => { if (!searchField.value) { @@ -288,25 +278,12 @@ function init() { document.addEventListener('keydown', (event) => { // Блокировка показа встроенного поиска в Firefox - if (event.code === 'Slash' && document.activeElement !== searchField) { + if ((event.code === 'Slash' || event.code === 'NumpadDivide') && document.activeElement !== searchField) { event.preventDefault() } }) document.addEventListener('keyup', (event) => { - if (event.code === 'Escape') { - queueMicrotask(() => { - searchForm.reset() - searchField.focus() - }) - } - - if (event.code === 'Slash' && document.activeElement !== searchField) { - queueMicrotask(() => { - searchField.focus() - }) - } - if (event.code === 'Enter' && document.activeElement === searchField) { queueMicrotask(() => { document.querySelector(SEARCH_HIT_LINK_SELECTOR)?.focus() diff --git a/src/styles/blocks/article-heading.css b/src/styles/blocks/article-heading.css index 037dcf3c..37631bcc 100644 --- a/src/styles/blocks/article-heading.css +++ b/src/styles/blocks/article-heading.css @@ -1,7 +1,13 @@ .article-heading { + scroll-margin-block: calc(var(--header-height) * 1px + 1rem); font-size: var(--font-size); line-height: var(--line-height); - scroll-margin: calc((var(--fixed-header-height, 0) * 1px) + 1rem); +} + +@media (width >= 1024px) { + .article-heading { + scroll-margin-block: calc(var(--header-height) * 1px + 2rem); + } } .article-heading__title { diff --git a/src/styles/blocks/article-image.css b/src/styles/blocks/article-image.css index c20aab61..2792b6cc 100644 --- a/src/styles/blocks/article-image.css +++ b/src/styles/blocks/article-image.css @@ -1,5 +1,5 @@ .article-image { - --aspect-ratio: 16 / 9; + --aspect-ratio: 16 / 7; display: grid; grid-template-columns: 1fr auto; grid-column-gap: 1em; diff --git a/src/styles/blocks/article-nav.css b/src/styles/blocks/article-nav.css index 7e206ec1..fbc332af 100644 --- a/src/styles/blocks/article-nav.css +++ b/src/styles/blocks/article-nav.css @@ -1,138 +1,127 @@ .article-nav { --is-nav-open: 0; - --button-height: 108px; - --lightness: calc(100% - var(--is-dark-theme-on) * 80%); + display: block; + position: relative; + font-size: 17px; + border-bottom: 1px solid var(--active-link-background, hsl(var(--color-fade))); } -.article-nav__button { - margin: 0; - position: absolute; - left: 0; - bottom: 100%; - overflow: visible; +@media (width >= 1024px) { + .article-nav { + --offset: 10px; + padding: calc(var(--offset) * 2); + font-size: inherit; + border-bottom: 0; + overflow: auto; + } +} + +.article-nav--open { + --is-nav-open: 1; +} + +.article-nav__toggle { + position: relative; width: 100%; - border: 0; - display: flex; - justify-content: center; - align-items: flex-end; - box-sizing: border-box; - min-height: var(--button-height); - padding: 30px 10px; - background-color: transparent; - cursor: pointer; - -webkit-tap-highlight-color: transparent; } -.article-nav__button-icon { - visibility: visible; - position: absolute; - left: 0; - right: 0; - bottom: 30px; - margin: auto; - transform: scale(calc(var(--on) + var(--off) * 1.5)); - opacity: var(--on); - width: 48px; - height: 48px; - border-radius: 50%; - color: var(--color-text); - background-color: hsl(0 0% var(--lightness)); - box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); - transition: transform 0.5s, opacity 0.5s; +@media (width >= 1024px) { + .article-nav__toggle { + display: none; + } } -.article-nav__button-icon--open { - --on: calc(1 - var(--is-nav-open)); - --off: var(--is-nav-open); +.article-nav__content { + box-sizing: border-box; + height: 0; + padding: 0; + line-height: 1.8; + overflow: hidden; + transition: padding 0.3s; } -.article-nav__button-icon--close { - --on: var(--is-nav-open); - --off: calc(1 - var(--is-nav-open)); +.article-nav--open .article-nav__content { + height: auto; + padding: var(--offset) 0; + transition: padding 0.3s; } -.article-nav__button::before { - content: ""; - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 100vh; - background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.33)); - transition: 0.5s; +@media (width >= 1024px) { + .article-nav__content { + display: initial; + overflow: auto; + height: 100%; + line-height: 1.8; + overscroll-behavior: contain; + } } -.article-nav__content { - overflow: auto; - overscroll-behavior: contain; - padding: var(--offset); - min-height: 0; +@media (width >= 1366px) { + .article-nav__content { + line-height: 1.6; + } } -.article-nav--open { - --is-nav-open: 1; +.toggle-button__icon--open .article-nav__toggle { + display: none; } -.article-nav:not(.article-nav--open) .article-nav__button { - visibility: hidden; - transition-delay: 0.5s; +.toggle-button { + box-sizing: border-box; + display: inline-flex; + justify-content: space-between; + align-items: center; + width: 100%; + font-size: inherit; + border: 0; + padding-inline-start: var(--offset); + background-color: transparent; + -webkit-tap-highlight-color: transparent; } -.article-nav:not(.article-nav--open) .article-nav__button::before { - visibility: hidden; - opacity: 0; +.toggle-button[aria-expanded="true"] { + position: absolute; + top: 0; + right: 0; + width: auto; + text-align: initial; } -@media (width <= 720px) { - .article-nav__button-icon { - left: auto; - right: var(--offset, 10px); - } +.toggle-button__icons { + position: relative; + width: 48px; + height: 48px; + overflow: hidden; } -@media not all and (width >= 1024px) { - .article-nav { - transform: translateY(calc((1 - var(--is-nav-open)) * 100%)); - position: fixed; - z-index: 1; - bottom: 0; - left: 0; - right: 0; - padding: 0; - max-height: calc(100% - var(--button-height)); - display: grid; - grid-template-rows: 1fr auto; - transition: transform 0.5s cubic-bezier(0.65, 0.05, 0.36, 1); - } +.toggle-button__icon { + position: absolute; + inset: 0; + color: var(--color-text); + background-color: transparent; + transform: scale(calc(var(--on) + var(--off)* 1.5)); + opacity: var(--on); + transition: transform 0.5s, opacity 0.5s; +} - .article-nav__content { - --active-link-lightness: calc(var(--is-light-theme-on) * 92%); - --active-link-background: hsl(0 0% var(--active-link-lightness)); - background-color: hsl(0 0% var(--lightness)); - } +.toggle-button__icon--close { + --on: var(--is-nav-open); + --off: calc(1 - var(--is-nav-open)); } -@media (width >= 1024px) { - .article-nav { - position: static; - transform: none; - display: block; - } +.toggle-button__icon--open { + --on: calc(1 - var(--is-nav-open)); + --off: var(--is-nav-open); +} - .article-nav__button { - display: none; - } +.article-nav--open .toggle-button__icon--close { + display: block; +} - .article-nav__content { - overflow: auto; - box-sizing: border-box; - height: 100%; - } +.toggle-text { + display: inline-block; } -@supports (filter: drop-shadow(0 0)) { - .article-nav__button-icon { - box-shadow: none; - filter: drop-shadow(0 4px 4px rgba(0, 0, 0, 0.25)); - } +.article-nav--open .toggle-text { + display: none; } diff --git a/src/styles/blocks/article.css b/src/styles/blocks/article.css index 7397778b..10189e8a 100644 --- a/src/styles/blocks/article.css +++ b/src/styles/blocks/article.css @@ -1,5 +1,3 @@ -.article {} - .article__header { grid-column-start: 1; grid-column-end: -1; @@ -9,7 +7,7 @@ .article__header-inner { box-sizing: border-box; padding: var(--offset); - padding-top: clamp(20px, 8%, 130px); + padding-top: clamp(20px, 3%, 130px); } .article__title { @@ -38,15 +36,13 @@ letter-spacing: var(--letter-spacing); } -.article__category-link {} - -.article__category-divider { +.article__category-devider { opacity: 0.6; } .article__image { margin-bottom: 60px; - margin-bottom: clamp(20px, 5.5%, 60px); + margin-bottom: clamp(20px, 2%, 60px); } .article__description { @@ -95,13 +91,11 @@ } .article__read-time { - margin-top: 1.5em; - margin-bottom: 1em; - font-size: 0.86em; + margin-top: 0.8em; + margin-bottom: 0; + font-size: var(--font-size-s); } -.article__layout {} - .article__aside { font-size: var(--font-size-s); line-height: var(--font-line-height-s); @@ -136,19 +130,11 @@ padding: calc(var(--offset) * 2) var(--offset); } -.article--with-cover {} - -.article--with-cover .article__header {} - -.article--with-cover .article__header-inner {} - .article:not(.article--with-cover) .article__header-inner { margin-left: 0; } @media not all and (width >= 1024px) { - .article {} - .article__layout { display: grid; grid-template-columns: minmax(0, 1fr); @@ -158,8 +144,6 @@ display: contents; } - .article__nav {} - .article__meta { order: 1; margin-top: 30px; @@ -210,10 +194,6 @@ } @media (width >= 1024px) { - .article {} - - .article__header-inner {} - .article__title { font-size: var(--font-size-xxl); line-height: var(--font-line-height-xxl); @@ -233,20 +213,17 @@ } .article__aside { - grid-row-end: span 2; + --header-offset: calc(var(--header-height) * 1px); position: sticky; top: var(--header-offset, 0); box-sizing: border-box; - max-height: calc(100vh - var(--header-offset, 0px)); - height: 100%; display: grid; grid-template-rows: minmax(0, 1fr) auto; + grid-row-end: span 2; + height: 100%; + max-height: calc(100vh - var(--header-offset, 0px)); transition: 0.2s cubic-bezier(0.65, 0.05, 0.36, 1); will-change: top, height; - } - - .article__aside--offset { - --header-offset: calc(var(--header-height, 0) * 1px); transition-duration: 0.2s; } @@ -262,8 +239,6 @@ padding-bottom: var(--offset); } - .article--with-cover {} - .article--with-cover .article__header { display: grid; grid-template-columns: var(--columns-template); diff --git a/src/styles/blocks/articles-group.css b/src/styles/blocks/articles-group.css index 52953048..8d1f2fab 100644 --- a/src/styles/blocks/articles-group.css +++ b/src/styles/blocks/articles-group.css @@ -1,8 +1,6 @@ -.articles-group {} - .articles-group__title { position: sticky; - top: calc(var(--offset, 0px) + var(--is-header-fixed, 0) * var(--header-height, 0) * 1px); + top: calc(var(--header-height) * 0.2px); margin-top: 0; margin-bottom: 12px; box-sizing: border-box; @@ -15,6 +13,12 @@ will-change: top; } +@media (width >= 1024px) { + .articles-group__title { + top: calc(var(--header-height) * 1.5px); + } +} + .articles-group__sub-title { margin-top: calc(14 / 15 * 1em); margin-bottom: calc(17 / 15 * 1em); @@ -29,8 +33,6 @@ text-transform: uppercase; } -.articles-group__section {} - .articles-group__section + .articles-group__section { margin-top: 30px; } @@ -67,7 +69,7 @@ font-size: var(--font-size-s); line-height: var(--font-line-height-s); white-space: nowrap; - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); } .articles-group--accent .articles-group__link { diff --git a/src/styles/blocks/base.css b/src/styles/blocks/base.css index cc284edd..09964bde 100644 --- a/src/styles/blocks/base.css +++ b/src/styles/blocks/base.css @@ -1,10 +1,6 @@ .base { - --is-header-fixed: 0; - --header-height: - calc( - var(--is-header-fixed) * var(--fixed-header-height, 0) + - (1 - var(--is-header-fixed)) * var(--not-fixed-header-height, 0) - ); + --is-header-sticky: 1; + --header-height: 56; font-size: var(--font-size-m, 100%); line-height: var(--font-line-height-m, 1.15); font-family: var(--font-family, sans-serif); @@ -14,7 +10,12 @@ scroll-behavior: smooth; } +/* TODO: рассчитать правильный отступ при наличии класса aria__controls--expanded */ + .base__body { margin: 0; - padding-top: calc(var(--is-header-fixed) * var(--not-fixed-header-height, 0) * 1px); +} + +.base__body:has(.header--open) { + top: 56px; } diff --git a/src/styles/blocks/block-code.css b/src/styles/blocks/block-code.css index 009a6ec7..3f581986 100644 --- a/src/styles/blocks/block-code.css +++ b/src/styles/blocks/block-code.css @@ -23,7 +23,7 @@ font-size: 0.6em; line-height: 1; letter-spacing: 0.025em; - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); border-radius: 2em; transition: opacity 0.2s; } diff --git a/src/styles/blocks/breadcrumbs.css b/src/styles/blocks/breadcrumbs.css index 5ba42070..251095fb 100644 --- a/src/styles/blocks/breadcrumbs.css +++ b/src/styles/blocks/breadcrumbs.css @@ -1,14 +1,17 @@ .breadcrumbs { display: flex; align-items: baseline; + font-size: var(--font-size-l); } -.breadcrumbs__text { - --stroke-width: 2px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - text-underline-offset: 0.2em; +.header__breadcrumbs { + min-width: 0; +} + +@media not all and (width >= 768px) { + .header--sticky .header__breadcrumbs { + flex-wrap: wrap; + } } .breadcrumbs__item { @@ -16,9 +19,15 @@ align-items: baseline; } -.breadcrumbs__item--shrink { - flex-shrink: 1; - min-width: 0; +.breadcrumbs__text { + --stroke-width: 2px; + --text-font-size: 0.85em; + letter-spacing: -.08em; + line-height: 1; + white-space: nowrap; + text-overflow: ellipsis; + text-underline-offset: 0.2em; + overflow: hidden; } .breadcrumbs .link::after, diff --git a/src/styles/blocks/callout.css b/src/styles/blocks/callout.css index 392178a4..76678491 100644 --- a/src/styles/blocks/callout.css +++ b/src/styles/blocks/callout.css @@ -1,6 +1,6 @@ .callout { --padding: 10px; - --code-lines-background: var(--color-fade); + --code-lines-background: hsl(var(--color-fade)); display: flex; flex-wrap: wrap; align-items: baseline; @@ -9,7 +9,7 @@ padding: 10px; overflow-wrap: break-word; border-radius: 6px; - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); } .callout__icon { diff --git a/src/styles/blocks/cookie-notification.css b/src/styles/blocks/cookie-notification.css index 65e6ef4c..d45747c8 100644 --- a/src/styles/blocks/cookie-notification.css +++ b/src/styles/blocks/cookie-notification.css @@ -1,6 +1,6 @@ .cookie-notification { position: fixed; - z-index: 2; + z-index: 3; bottom: 0; left: 0; right: 0; diff --git a/src/styles/blocks/details.css b/src/styles/blocks/details.css index ac4b1d92..da090887 100644 --- a/src/styles/blocks/details.css +++ b/src/styles/blocks/details.css @@ -1,6 +1,6 @@ .details { overflow: hidden; - border: 1px solid var(--color-fade); + border: 1px solid hsl(var(--color-fade)); border-radius: 6px; } @@ -10,7 +10,7 @@ .details__summary { padding: var(--offset); - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); outline-offset: -2px; outline-width: 2px; } diff --git a/src/styles/blocks/filter-group.css b/src/styles/blocks/filter-group.css index c27cb848..60b7d162 100644 --- a/src/styles/blocks/filter-group.css +++ b/src/styles/blocks/filter-group.css @@ -3,3 +3,9 @@ grid-gap: 6px; justify-items: start; } + +@media not all and (width >= 768px) { + .filter-group { + grid-gap: 10px; + } +} diff --git a/src/styles/blocks/filter-panel.css b/src/styles/blocks/filter-panel.css index b2d1fd14..4a5d741d 100644 --- a/src/styles/blocks/filter-panel.css +++ b/src/styles/blocks/filter-panel.css @@ -8,7 +8,7 @@ .filter-panel__inner { margin: 0; - padding: 20px var(--offset); + padding: var(--offset); border: 0; min-height: 0; background-color: var(--color-background); @@ -34,7 +34,8 @@ opacity: var(--is-filter-open); position: absolute; inset: 0; - background-color: rgb(0 0 0 / 0.33); + background-color: hsl(var(--color-fade) / 0.45); + backdrop-filter: grayscale(1); transition: 0.5s; pointer-events: none; } @@ -50,7 +51,6 @@ transition: transform 0.5s cubic-bezier(0.65, 0.05, 0.36, 1), opacity calc(0.5s * (var(--is-filter-open))); - background-color: hsl(0 0% var(--lightness)); } .filter-panel__button { @@ -72,19 +72,3 @@ display: none; } } - -@media (width >= 1024px) { - .filter-panel { - /* position: sticky; - top: calc(var(--header-height, 0) * 1px); - height: calc(100vh - var(--header-height, 0) * 1px); - grid-row-end: span 2; - display: grid; */ - } - - .filter-panel__inner { - /* display: flex; - flex-direction: column; - min-height: 100%; */ - } -} diff --git a/src/styles/blocks/float-button.css b/src/styles/blocks/float-button.css index 691b8d01..b646319d 100644 --- a/src/styles/blocks/float-button.css +++ b/src/styles/blocks/float-button.css @@ -11,6 +11,8 @@ } .float-button__icons { + --stroke-opacity: 0.3; + --stroke-color: hsl(var(--color-base-text) / var(--stroke-opacity)); visibility: visible; position: absolute; left: 0; @@ -19,9 +21,10 @@ margin: auto; width: 48px; height: 48px; + border: 1px solid var(--stroke-color); border-radius: 50%; color: var(--color-text); - background-color: hsl(0 0% var(--lightness)); + background-color: var(--color-background); box-shadow: 0 4px 4px rgb(0 0 0 / 25%); } diff --git a/src/styles/blocks/footer.css b/src/styles/blocks/footer.css index 4aee802b..4fa86488 100644 --- a/src/styles/blocks/footer.css +++ b/src/styles/blocks/footer.css @@ -1,5 +1,5 @@ .footer { - border-block-start: 1px solid hsl(var(--color-base-text) / 0.3); + border-block-start: 1px solid var(--color-border); padding: 20px 10px; display: flex; gap: 30px; diff --git a/src/styles/blocks/header-animation.css b/src/styles/blocks/header-animation.css new file mode 100644 index 00000000..9185b5d2 --- /dev/null +++ b/src/styles/blocks/header-animation.css @@ -0,0 +1,77 @@ +/* анимируем появление строки поиска, когда меню открывается */ +.header__controls .header__search { + transition: opacity var(--header-animation-time); +} + +/* анимируем булочку */ +.logo { + --image-font-size: 0.85em; + --logo-letter-spacing: -0.14em; +} + +.logo__image { + --is-animation: 0; +} + +.logo__image::before { + --colors: + var(--accent-color), + var(--accent-color), + var(--color-css), + var(--color-js), + var(--color-tools), + var(--color-recipes), + var(--color-a11y), + var(--accent-color), + var(--accent-color); + --parts: 8; + content: ''; + opacity: var(--is-animation); + position: absolute; + z-index: -1; + left: 0; + right: 0; + top: 0; + height: calc(var(--parts) * 100%); + background-image: linear-gradient(var(--colors)); + transition: opacity 0.5s; +} + +.logo__image--animation { + --is-animation: 1; +} + +@keyframes logoAnimation { + to { + transform: + translateY(-100%) + translateY(calc(100% / (var(--parts) - 1))); + } +} + +.logo__image--animation::before { + animation: logoAnimation 0.75s ease-out infinite both; +} + +.logo__symbols { + transition: opacity 0.2s; + + /* для устранения скачков в Safari */ + transform: translateZ(0); +} + +.logo__symbols--main { + opacity: calc(1 - var(--is-animation)); +} + +.logo__symbols--search { + opacity: var(--is-animation); +} + +.logo__eye { + top: -0.08em; +} + +.logo__nose { + top: -0.015em; +} diff --git a/src/styles/blocks/header-button.css b/src/styles/blocks/header-button.css new file mode 100644 index 00000000..25e44133 --- /dev/null +++ b/src/styles/blocks/header-button.css @@ -0,0 +1,114 @@ +.header-button { + position: relative; + display: block; + margin: 0; + padding: 0; + border: 0; + background-color: transparent; + color: inherit; + appearance: none; + cursor: pointer; +} + +.header-button::after { + content: ""; + position: absolute; + inset: -10px; +} + +/* увеличиваем область клика для кнопки открытия */ +.header:has(.header-button):not(.header--open) .header-button:not(.search__reset-button) { + padding: 10px 0; +} + +/* показываем/скрываем внутренности гамбургера (в хедере) */ +.header-button-content--open { + --is-menu-open: 1; +} + +.header--open .header-button-content--open { + display: none; +} + +.header-button-content--close { + display: none; + align-items: center; + gap: 10px; +} + +.header--open .header-button-content--close { + display: flex; +} + +@media all and (width >= 1024px) { + .header-button-content--close { + flex-direction: column-reverse; + } +} + +/* стили иконок из гамбургера */ +.header-button-icon { + transition: opacity 0.2s; +} + +.header-button:hover .header-button-icon { + opacity: 0.7; +} + +.header-button-icon--open { + display: flex; + align-items: center; + gap: 7px; +} + +.header-button-icon__dot { + --gap: 7px; + flex: 0 0 auto; + width: 6px; + height: 6px; + gap: 7px; + background-color: currentColor; + border-radius: 50%; +} + +@media (width >= 1024px) { + .header-button-icon--open { + --gap: 10px; + gap: 10px; + } + + .header-button-icon__dot { + width: 8px; + height: 8px; + } +} + +.header-button-icon--close { + width: 30px; + height: 30px; +} + +@media (width >= 1024px) { + .header-button-icon--close { + width: 35px; + height: 35px; + } +} + +@media (width >= 1366px) { + .header-button-icon--close { + width: 37px; + height: 37px; + } +} + +@media (width >= 1680px) { + .header-button-icon--close { + width: 43px; + height: 43px; + } +} + +.search__reset-button { + margin-inline-start: 20px; +} diff --git a/src/styles/blocks/header.css b/src/styles/blocks/header.css index 5340f379..2eb7af09 100644 --- a/src/styles/blocks/header.css +++ b/src/styles/blocks/header.css @@ -1,363 +1,245 @@ +:root { + --menu-padding-min: 10px; + --menu-padding-max: 20px; +} + .header { --header-bg-color: var(--accent-color, var(--color-background)); - --search-input-height: 0.7em; - --header-animation-time: 0.2s; - position: relative; - z-index: 2; + --header-border-color: var(--accent-color, var(--color-border)); + --search-input-height: 0.4em; background-color: var(--color-background); + z-index: 3; } -/* фон при открытом меню */ -.header::before:not(.header--open) { - content: ""; - position: fixed; - z-index: 2; - opacity: 0.3; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: var(--color-text); - transition: - opacity var(--header-animation-time), - visibility var(--header-animation-time); -} - -/* "тень" от фиксированной шапки */ -.header::after { - content: ""; - position: absolute; - left: 0; - right: 0; - top: 100%; - margin-top: -1px; - height: 40px; - background: - linear-gradient( - to bottom, - hsl(var(--color-base-background)/1) 0%, - hsl(var(--color-base-background)/0.889) 2.5%, - hsl(var(--color-base-background)/0.856) 6%, - hsl(var(--color-base-background)/0.806) 10.4%, - hsl(var(--color-base-background)/0.742) 15.6%, - hsl(var(--color-base-background)/0.667) 21.5%, - hsl(var(--color-base-background)/0.583) 28%, - hsl(var(--color-base-background)/0.495) 35.1%, - hsl(var(--color-base-background)/0.405) 42.5%, - hsl(var(--color-base-background)/0.317) 50.4%, - hsl(var(--color-base-background)/0.233) 58.5%, - hsl(var(--color-base-background)/0.158) 66.8%, - hsl(var(--color-base-background)/0.094) 75.2%, - hsl(var(--color-base-background)/0.044) 83.6%, - hsl(var(--color-base-background)/0.011) 91.9%, - hsl(var(--color-base-background)/0) 100% - ); - pointer-events: none; - transition: opacity var(--header-animation-time); -} - -.header__inner { +/* всегда открытое меню (главная) */ +.header--static { position: relative; - padding: 10px; - display: flex; - justify-content: space-between; - align-items: center; - background-color: var(--header-bg-color); } -.header.header--main:not(.header--open) { - background: none; +/* фиксированное меню на мобилках */ +.header--sticky { + position: static; } -.header.header--main:not(.header--open)::after { - margin-top: 0; - background: - linear-gradient( - to bottom, - hsla(var(--color-base-background) / 0.59), - hsla(var(--color-base-background) / 0) - ); +@media (width >= 768px) { + .header--sticky { + position: sticky; + top: 0; + } } -.header.header--main:not(.header--open) .header__inner { - background: - linear-gradient( - to bottom, - hsla(var(--color-base-background) / 0.75), - hsla(var(--color-base-background) / 0.59) - ); +.header--open { + position: fixed; + width: 100%; } -.header__inner--main { - font-size: var(--font-size-l); - letter-spacing: -0.06em; - line-height: var(--font-line-height-l); - font-family: var(--font-family); +@media (height <= 450px) { + .header--open { + position: fixed; + height: 100%; + overflow-y: scroll; + } } -.header--main .header__inner--main { - height: calc(var(--font-line-height-l) * 1.25); +@media (width >= 768px) { + .header--open { + position: sticky; + width: 100%; + } + + .header--open .header__menu { + position: fixed; + } } -.header__inner--menu { - position: fixed; - z-index: 2; - top: 0; - left: 0; - right: 0; - padding-top: 20px; +/* содержимое главного меню (без дропдауна) */ +.header__controls { + --letter-spacing: -0.06em; display: grid; - align-content: start; grid-template-areas: - "logo button" - "search search" - "search-output search-output" - "list list"; - grid-template-rows: var(--font-size-xl) repeat(3, auto); - font-size: calc(var(--font-size-xl) * 0.95); - line-height: calc(var(--font-line-height-xl) * 0.95); - letter-spacing: -0.06em; - background-color: var(--color-background); - transition: - transform var(--header-animation-time) cubic-bezier(0.65, 0.05, 0.36, 1), - opacity 0s, - visibility 0s; + "logo button" + "search search-output"; + grid-template-columns: 1fr auto; + padding: var(--menu-padding-min); + font-family: var(--font-family); + font-size: var(--font-size-l); + line-height: var(--font-line-height-l); + background-color: var(--header-bg-color); + transition: all 0.2s; } -/* удаляем первое меню, когда показывается второе */ -.header--open > .header__inner--main { - visibility: hidden; +.header__controls--shrink { + box-shadow: 0 1px 0 0 var(--header-border-color); } -/* скрываем первое меню на главной */ -.header--main.header--open > .header__inner--main { - display: none; +.header--open > .header__controls--shrink { + box-shadow: none; } -.header--main.header--open > .header__inner--menu { - position: relative; +@media (width >= 768px) { + .header__controls--shrink { + padding: 7px 10px; + } } -.header__breadcrumbs { - min-width: 0; - line-height: 1.25; +@media (width >= 1024px) { + .header__controls { + --gap: 20px; + padding: var(--menu-padding-max); + display: flex; + justify-content: space-between; + } + + .header__controls--shrink { + padding: var(--menu-padding-min) var(--menu-padding-max); + } } -.header__title-code { - font: inherit; +.header--open .header__controls { + background-color: var(--color-background); } .header__divider { - opacity: 0.3; - margin: 0 0.2em; + margin-left: 0.2em; + margin-right: 0.2em; font-family: var(--font-family); + font-size: 0.85em; letter-spacing: var(--letter-spacing); + opacity: 0.3; } .header__divider::before { content: "/"; } -.header__divider--large { - font-size: calc(var(--font-size-xl) * 0.85); - line-height: var(--font-line-height-xl); -} - -.header__logo { - display: flex; - align-self: center; - align-items: center; -} - -.header__inner--menu .header__search { +/* поиск */ +.header__controls .header__search { + display: none; grid-area: search; - align-self: flex-start; - font-family: var(--font-family); - font-size: calc(var(--font-size-xl) * 0.85); - line-height: calc(var(--font-line-height-xl) * 0.85); - letter-spacing: -0.08em; - margin-top: var(--gap, 16px); -} - -@media (width >= 1024px) { - .header__inner--menu .header__search { - margin-top: -14px; - } -} - -.header__menu { - grid-area: list; - margin-top: var(--gap, 16px); - margin-bottom: 1.7%; -} - -@media (width >= 1024px) { - .header__menu { - margin-top: calc(4 * var(--gap, 16px)); - } -} - -@media (width >= 1366px) { - .header__menu { - margin-top: calc(6 * var(--gap, 16px)); - } -} - -@media not all and (width >= 768px) { - .header__menu { - --gap: 16px; - } -} - -@media (width >= 768px) { - .header__menu { - --gap: 14px; - } + grid-column-end: none; } -@media (width >= 1024px) { - .header__menu { - --gap: 6px; +@media (width >= 1680px) { + .header__controls .header__search { + position: relative; + top: -2px; } } -@media (width >= 1680px) { - .header__menu { - --gap: 9px; - } +/* показываем поиск на главной и с раскрытым дропдауном */ +.header--static .header__search, +.header--open .header__search { + display: block; } -.header__toggle { - margin-left: 20px; +/* закрытие/раскрытие меню */ +.header__buttons { display: flex; align-items: center; justify-content: flex-end; -} - -.header__inner--menu .header__toggle { - grid-area: button; - align-self: flex-start; margin-left: 20px; + gap: 16px; } -.header--fixed { - position: fixed; - top: 0; - left: 0; - right: 0; +.hotkey__key { + font-family: inherit; + text-transform: uppercase; + display: none; } -.header--animating { - animation-name: fixedHeaderAnimation; - animation-duration: var(--header-animation-time); - animation-fill-mode: both; - animation-timing-function: cubic-bezier(0.65, 0.05, 0.36, 1); +/* скрываем/показываем горячие клавиши */ +.hotkey--close { + display: none; } -.header--fixed-show { - animation-direction: normal; +.hotkey--search { + display: none; } -.header--fixed-hide { - animation-direction: reverse; - animation-duration: 0.2s; - animation-timing-function: ease; +.header--open .hotkey--search { + display: none; } -@keyframes fixedHeaderAnimation { - from { - transform: translateY(-100%); +@media (width >= 1024px) { + .hotkey__key, + .hotkey--search, + .header--open .hotkey--close { + display: inline-block; } } -.header:not(.header--fixed)::after { - opacity: 0; -} +/* TODO: хранить стили из .header__menu в .nav-list (в одном месте) */ -.header:not(.header--fixed) .header__title { - display: none; -} +/* дропдаун с разделами */ +.header__menu { + /* position: absolute; */ -.header--open { - z-index: 3; - animation: none; -} + /* position: fixed; */ + width: 100%; -.header--open::after { - display: none; + /* height: 100%; */ + font-size: calc(var(--font-size-xl) * 0.95); + line-height: calc(var(--font-line-height-xl) * 0.95); + letter-spacing: -0.06em; + background-color: var(--color-background); } -.header:not(.header--open)::before { - opacity: 0; - visibility: hidden; -} +/* @media (width >= 1024px) { + .header__menu { + position: absolute; + } +} */ -.header--static .header__toggle { - display: none; +/* всегда раскрытый список разделов на главной */ +.header--static .header__menu { + position: static; + height: auto; } -.header:not(.header--open, .header--static) .header__inner--menu { - transform: translateY(-100%); - opacity: 0; +.header:not(.header--open, .header--static) .header__menu { visibility: hidden; - transition-delay: 0s, var(--header-animation-time), var(--header-animation-time); + height: 0; + opacity: 0; } -@media not all and (width >= 1366px) { - .header__category--standalone { - height: 1.25em; - } +/* затемняем фон сайта, когда меню открыто */ +.base__body:has(.header--open)::after { + content: ''; + position: fixed; + inset: 0; + background-color: hsl(var(--color-fade) / 0.45); + backdrop-filter: grayscale(1); + z-index: 2; +} - .header:not(.header--fixed) .header__category--standalone { - display: none; - } +/* скрываем крошки, когда меню открыто */ +.header--open .header__category { + display: none; } @media not all and (width >= 768px) { .header__category:not(.header__category--standalone) { display: none; } - - .header--fixed .header__breadcrumbs { - flex-wrap: wrap; - } - - .header--fixed .header__title { - margin-top: 10px; - flex-basis: 100%; - } } -@media all and (width >= 430px) { - .header__category.header__category--visible { - display: flex; - } -} - -@media (width >= 768px) { - .header__breadcrumbs { - font-size: var(--font-size-l); +/* скрываем крошку на мобильных на странице раздела */ +@media (width < 768px) { + .header__category--standalone { + display: none; } } -@media (width >= 1024px) { - .header__inner { - padding-left: 20px; - padding-right: 20px; - } - - .header__inner--menu { - grid-template-areas: - "logo search button" - ". search-output ." - ". list ."; - grid-auto-columns: auto 1fr auto; - grid-template-rows: var(--search-input-height) auto; +/* подтягиваем контент под растущий хэдер */ +@media (width >= 768px) and (width < 1024px) { + .header--open + .doc { + position: relative; + top: -50px; } } -@media (width >= 1680px) { - .header__inner--menu { - padding-bottom: 20px; +@media (width < 768px) { + .header--open + .doc .article__header { + padding-block-start: 51px; } } diff --git a/src/styles/blocks/hotkey.css b/src/styles/blocks/hotkey.css index 694e1d20..0fcaf806 100644 --- a/src/styles/blocks/hotkey.css +++ b/src/styles/blocks/hotkey.css @@ -1,25 +1,25 @@ .hotkey { - opacity: 0.7; min-width: 14px; padding: 1px 6px; - border: 1px solid hsl(var(--color-base-text) / 0.3); text-align: center; - font-size: 17px; - line-height: 1; font-family: var(--font-family); + font-size: 20px; + line-height: 1.2; letter-spacing: var(--letter-spacing); - text-transform: uppercase; + border: 1px solid var(--color-border); border-radius: 5px; + opacity: 0.7; + user-select: none; } -@media not all and (width >= 768px) { +@media (width <= 1366px) { .hotkey { - display: none; + font-size: 18px; } } -@media (width >= 1024px) { +@media not all and (width >= 768px) { .hotkey { - font-size: 20px; + display: none; } } diff --git a/src/styles/blocks/index-block.css b/src/styles/blocks/index-block.css index 7f051b8b..5fdf0840 100644 --- a/src/styles/blocks/index-block.css +++ b/src/styles/blocks/index-block.css @@ -16,6 +16,12 @@ background-color: var(--accent-color); } +@media (width >= 768px) and (width < 1366px) { + .index-block__header { + padding: calc(2 * var(--offset)); + } +} + .index-block__title { margin-top: 0; margin-bottom: 10px; @@ -24,10 +30,6 @@ font-weight: normal; } -.index-block__description {} - -.index-block__description--aside {} - .index-block__filter { margin: 0; position: sticky; @@ -40,12 +42,6 @@ background-color: var(--color-background); } -.index-block__filter-legend {} - -.index-block__filter-control {} - -.index-block__main {} - @media not all and (width >= 1366px) { .index-block__inner { display: grid; @@ -64,7 +60,7 @@ align-items: center; justify-content: center; gap: var(--offset, 20px); - border-block-start: 1px solid hsl(var(--color-base-text) / 0.3); + border-block-start: 1px solid var(--color-border); font-size: var(--font-size-m); line-height: var(--font-line-height-m); } @@ -102,15 +98,13 @@ opacity: 0; } - .index-block__description {} - .index-block__filter { grid-column: 1; padding: var(--offset); padding-right: 0; flex-direction: column; align-items: flex-start; - justify-content: end; + justify-content: flex-end; gap: 4px; } diff --git a/src/styles/blocks/index-section.css b/src/styles/blocks/index-section.css index 11517aeb..d8064304 100644 --- a/src/styles/blocks/index-section.css +++ b/src/styles/blocks/index-section.css @@ -23,7 +23,7 @@ } .index-section__item { - scroll-margin-block: calc(var(--header-height, 0) * 1px + 1em); + scroll-margin-block: calc(var(--header-height) * 1px + 1rem); position: relative; padding-bottom: var(--gutter); display: flow-root; @@ -31,6 +31,12 @@ break-inside: avoid; } +@media (width >= 1024px) { + .index-section__item { + scroll-margin-block: calc(var(--header-height) * 1px + 2rem); + } +} + .index-section__item::before { content: ""; opacity: 0; diff --git a/src/styles/blocks/inline-code.css b/src/styles/blocks/inline-code.css index deb9bddc..6164d321 100644 --- a/src/styles/blocks/inline-code.css +++ b/src/styles/blocks/inline-code.css @@ -5,5 +5,5 @@ font-family: var(--font-family); letter-spacing: var(--letter-spacing); border-radius: 2em; - background-color: var(--background-code-color, var(--color-fade)); + background-color: var(--background-code-color, hsl(var(--color-fade))); } diff --git a/src/styles/blocks/intro.css b/src/styles/blocks/intro.css index d908ee1c..bfe9e9d1 100644 --- a/src/styles/blocks/intro.css +++ b/src/styles/blocks/intro.css @@ -41,7 +41,7 @@ grid-template-rows: calc(1.5 * var(--font-size-l)) auto min-content; gap: calc(2 * var(--gutter)); padding: var(--gutter); - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); border-radius: 6px; } diff --git a/src/styles/blocks/link.css b/src/styles/blocks/link.css index 9a8a159d..8d53e961 100644 --- a/src/styles/blocks/link.css +++ b/src/styles/blocks/link.css @@ -61,3 +61,34 @@ .online .link--non-cached:not(.nav-list__link, .article-indexes-list__link)::after { display: none; } + +.skip-link { + position: absolute; + overflow: hidden; + top: auto; + left: -10000px; + width: 1px; + height: 1px; + padding: 16px 52px; + background-color: var(--color-background); + z-index: 4; +} + +.skip-link:focus-visible { + top: 0; + left: 0; + width: auto; + height: auto; +} + +@media (width >= 1024px) { + .skip-link { + padding: 23px 56px; + } +} + +@media (width >= 1680px) { + .skip-link { + padding: 26px 62px; + } +} diff --git a/src/styles/blocks/linked-article.css b/src/styles/blocks/linked-article.css index 8bcc0d31..a6881c6b 100644 --- a/src/styles/blocks/linked-article.css +++ b/src/styles/blocks/linked-article.css @@ -60,7 +60,6 @@ flex: 0 0 auto; opacity: 1; display: inline-block; - text-transform: none; } .linked-article__plus { diff --git a/src/styles/blocks/logo.css b/src/styles/blocks/logo.css index 2a9bb9b0..689a3438 100644 --- a/src/styles/blocks/logo.css +++ b/src/styles/blocks/logo.css @@ -12,7 +12,6 @@ } .logo__image { - --is-animation: 0; --accent-color: var(--color-html); align-self: center; position: relative; @@ -29,50 +28,12 @@ user-select: none; } -.logo__image--contrast { +/* добавляем контрастную рамку для лого */ +.logo__image--contrast, +.header--open .logo__image--custom { border: 1px var(--logo-border-color) solid; } -.logo__image::before { - --colors: - var(--accent-color), - var(--accent-color), - var(--color-css), - var(--color-js), - var(--color-tools), - var(--color-recipes), - var(--color-a11y), - var(--accent-color), - var(--accent-color); - --parts: 8; - content: ''; - opacity: var(--is-animation); - position: absolute; - z-index: -1; - left: 0; - right: 0; - top: 0; - height: calc(var(--parts) * 100%); - background-image: linear-gradient(var(--colors)); - transition: opacity 0.5s; -} - -.logo__image--animation { - --is-animation: 1; -} - -@keyframes logoAnimation { - to { - transform: - translateY(-100%) - translateY(calc(100% / (var(--parts) - 1))); - } -} - -.logo__image--animation::before { - animation: logoAnimation 0.75s ease-out infinite both; -} - .logo__symbols { grid-area: 1 / 1 / -1 / -1; margin-right: calc(var(--logo-letter-spacing) * -1); @@ -80,21 +41,10 @@ line-height: 1; letter-spacing: var(--logo-letter-spacing); text-decoration: none; - transition: opacity 0.2s; - transform: translateZ(0); /* для устранения скачков в Safari */ -} - -.logo__symbols--main { - opacity: calc(1 - var(--is-animation)); -} - -.logo__symbols--search { - opacity: var(--is-animation); } .logo__eye { position: relative; - top: -0.08em; } .logo__eye:first-child { @@ -105,7 +55,6 @@ position: relative; font-size: calc(var(--image-font-size) * 10 / 7); line-height: calc(var(--image-font-size) * 7 / 10); - top: -0.015em; letter-spacing: calc(var(--logo-letter-spacing) * 1.5); } diff --git a/src/styles/blocks/menu-toggle.css b/src/styles/blocks/menu-toggle.css deleted file mode 100644 index c54a4292..00000000 --- a/src/styles/blocks/menu-toggle.css +++ /dev/null @@ -1,77 +0,0 @@ -.menu-toggle { - position: relative; - appearance: none; - margin: 0; - display: block; - padding: 0; - border: 0; - background-color: transparent; - color: inherit; - cursor: pointer; -} - -.menu-toggle::after { - content: ""; - position: absolute; - inset: -10px; -} - -.menu-toggle__inner { - display: flex; - gap: 10px; - align-items: center; -} - -@media all and (width >= 1024px) { - .menu-toggle__inner--close { - flex-direction: column-reverse; - } -} - -.menu-toggle__icon { - transition: opacity 0.2s; -} - -.menu-toggle__icon--open { - display: flex; - align-items: center; - gap: 7px; -} - -.menu-toggle__icon--close { - width: 30px; - height: 30px; -} - -.menu-toggle__dot { - flex: 0 0 auto; - width: 6px; - height: 6px; - gap: 7px; - background-color: currentColor; - border-radius: 50%; -} - -.menu-toggle--open { - --is-menu-open: 1; -} - -.menu-toggle:hover .menu-toggle__icon { - opacity: 0.7; -} - -@media (width >= 1024px) { - .menu-toggle__icon--open { - gap: 10px; - } - - .menu-toggle__dot { - width: 8px; - height: 8px; - } - - .menu-toggle__icon--close { - width: 45px; - height: 45px; - } -} diff --git a/src/styles/blocks/nav-list.css b/src/styles/blocks/nav-list.css index 0bcd2e77..458c7c47 100644 --- a/src/styles/blocks/nav-list.css +++ b/src/styles/blocks/nav-list.css @@ -1,18 +1,60 @@ +:root { + --list-padding-min: 10px; + --list-padding-max: 20px; + --gap: 16px; +} + .nav-list { --stroke-size: calc(6 / 48 * 1em); --transition: 150ms ease-in-out; display: grid; - gap: var(--gap); + padding-top: var(--list-padding-min); + padding-bottom: var(--list-padding-min); + padding-right: var(--list-padding-min); + padding-left: var(--list-padding-min); + gap: 16px; + background: var(--color-background); +} + +@media (width >= 768px) { + .nav-list { + --block-padding: 1px; + gap:14px; + line-height: calc(42 / 36); + } +} + + +/* TODO: рассчитать отступ слева более элегантно */ + +@media (width >= 1024px) { + .nav-list { + --block-padding: 6px; + --gap: 6px; + padding-top: 0; + padding-bottom: var(--list-padding-max); + padding-right: var(--list-padding-max); + padding-left: calc(37*var(--gap)); + gap: 6px; + line-height: inherit; + } +} + +@media (width >= 1366px) { + .nav-list { + padding-left: calc(38*var(--gap)); + } +} + +@media (width >= 1680px) { + .nav-list { + padding-left: calc(45*var(--gap)); + } } .nav-list__item { position: relative; z-index: 0; - - /* padding-top: var(--block-padding); - padding-bottom: var(--block-padding); - padding-left: 10px; - padding-right: 10px; */ } .nav-list__link { @@ -56,11 +98,17 @@ position: relative; z-index: -1; display: block; - height: var(--stroke-size); + height: round(var(--stroke-size), 1px); background-color: var(--accent-color); border-radius: 1em; } +@supports not (height: round(1.5px, 1px)) { + .nav-list__link-text::after { + height: var(--stroke-size); + } +} + .nav-list__link:hover::after { opacity: calc(1 - var(--is-dark-theme-on) * 0.6); visibility: visible; @@ -70,27 +118,3 @@ opacity: 0; transition: var(--transition); } - -@media not all and (width >= 768px) { - .nav-list {} -} - -@media (width >= 768px) { - .nav-list { - --block-padding: 1px; - line-height: calc(42 / 36); - } -} - -@media (width >= 1024px) { - .nav-list { - --block-padding: 6px; - line-height: inherit; - } -} - -@media (width >= 1680px) { - .nav-list { - line-height: 1; - } -} diff --git a/src/styles/blocks/people-page.css b/src/styles/blocks/people-page.css index b0b6b2b5..347b1bcf 100644 --- a/src/styles/blocks/people-page.css +++ b/src/styles/blocks/people-page.css @@ -35,7 +35,7 @@ .people-page__filter { position: sticky; - top: calc(var(--is-header-fixed) * var(--header-height) * 1px + var(--offset)); + top: calc(var(--header-height) * 1px); flex: 0 0 14em; box-sizing: border-box; transition: top 0.6s; diff --git a/src/styles/blocks/person-avatar.css b/src/styles/blocks/person-avatar.css index c326e453..a51cbcec 100644 --- a/src/styles/blocks/person-avatar.css +++ b/src/styles/blocks/person-avatar.css @@ -24,5 +24,5 @@ justify-content: center; align-items: center; font-family: var(--font-family); - background-color: var(--accent-color, var(--color-fade)); + background-color: var(--accent-color, hsl(var(--color-fade))); } diff --git a/src/styles/blocks/person-badges.css b/src/styles/blocks/person-badges.css index df1a56d3..1d263f12 100644 --- a/src/styles/blocks/person-badges.css +++ b/src/styles/blocks/person-badges.css @@ -121,7 +121,7 @@ height: max-content; padding: 30px; background-color: var(--color-background); - border: 1px solid var(--color-fade); + border: 1px solid hsl(var(--color-fade)); } @media (any-hover: hover) { diff --git a/src/styles/blocks/person-page.css b/src/styles/blocks/person-page.css index c399fda3..7010779e 100644 --- a/src/styles/blocks/person-page.css +++ b/src/styles/blocks/person-page.css @@ -145,7 +145,7 @@ .person-page__avatar { position: sticky; - top: calc(var(--is-header-fixed) * var(--header-height) * 1px); + top: calc(var(--header-height) * 1px); transition: top 0.6s; } diff --git a/src/styles/blocks/search-page.css b/src/styles/blocks/search-page.css index 53cde374..2c53144c 100644 --- a/src/styles/blocks/search-page.css +++ b/src/styles/blocks/search-page.css @@ -3,19 +3,6 @@ min-height: 100vh; } -.search-page__header { - --search-input-height: 1.285em; - position: sticky; - top: 0; -} - -.search-page__header-inner { - display: grid; - grid-template-columns: auto 1fr auto; - align-items: center; - background-color: var(--color-background); -} - .search-page__aside { --lightness: calc(100% - var(--is-dark-theme-on) * 80%); position: relative; @@ -38,6 +25,8 @@ } .search-page__aside-icon-wrapper { + --stroke-opacity: 0.3; + --stroke-color: hsl(var(--color-base-text) / var(--stroke-opacity)); visibility: visible; position: absolute; left: 0; @@ -46,9 +35,10 @@ margin: auto; width: 48px; height: 48px; + border: 1px solid var(--stroke-color); border-radius: 50%; color: var(--color-text); - background-color: hsl(0 0% var(--lightness)); + background-color: var(--color-background); box-shadow: 0 4px 4px rgb(0 0 0 / 25%); } @@ -78,23 +68,16 @@ max-width: 809px; } -.search-page__empty {} - @media not all and (width >= 1024px) { .search-page { display: grid; grid-template-rows: auto 1fr auto auto; grid-template-areas: - "header" "main" "filter" "footer"; } - .search-page__header { - grid-area: header; - } - .search-page__aside { grid-area: filter; position: sticky; @@ -117,29 +100,6 @@ } @media not all and (width >= 768px) { - .search-page__header-inner { - grid-template-columns: auto 1fr; - grid-template-rows: auto auto; - font-size: 32px; - line-height: 34px; - } - - .search-page__search { - margin-top: 12px; - grid-row: 2; - grid-column-start: 1; - grid-column-end: -1; - } - - .search-page__header .search-page__toggle { - margin-top: 0; - } - - /* TODO: уменьшить специфичность */ - .search-page__header .search-page__header-inner .search-page__logo.search-page__logo { - font-size: 1em; - } - .search-page__aside { position: fixed; --is-filter-open: 0; @@ -150,7 +110,7 @@ display: flex; flex-direction: column; border-top: 0; - z-index: 2; + z-index: 3; } .search-page__aside::before { @@ -161,7 +121,8 @@ bottom: 0; left: 0; right: 0; - background-color: rgb(0 0 0 / 0.33); + background-color: hsl(var(--color-fade) / 0.45); + backdrop-filter: grayscale(1); transition: 0.5s; pointer-events: none; } @@ -178,7 +139,7 @@ transition: transform 0.5s cubic-bezier(0.65, 0.05, 0.36, 1), opacity calc(0.5s * (var(--is-filter-open))); - background-color: hsl(0 0% var(--lightness)); + background-color: var(--color-background); } .search-page__aside-button { @@ -209,11 +170,6 @@ grid-template-rows: auto 1fr; } - .search-page__header { - grid-column-start: 1; - grid-column-end: -1; - } - .search-page__aside { position: sticky; top: calc(var(--header-height, 0) * 1px); diff --git a/src/styles/blocks/search.css b/src/styles/blocks/search.css index ea6c15b9..6b894ac1 100644 --- a/src/styles/blocks/search.css +++ b/src/styles/blocks/search.css @@ -1,15 +1,29 @@ .search { - --search-input-height: calc(var(--font-size-xl) * 1.25); + margin-top: var(--gap, 10px); position: relative; display: grid; font-family: var(--font-family); - font-size: calc(var(--font-size-xl) * 0.85); - line-height: calc(var(--font-line-height-xl) * 0.85); + font-size: calc(var(--font-size-xl) * 0.75); + line-height: var(--font-line-height-xl); letter-spacing: var(--letter-spacing); } -.search__input, -.search__controls { +@media (width >= 760px) { + .search { + --gap: 16px; + align-self: flex-start; + flex-grow: 1; + } +} + +@media (width >= 1024px) { + .search { + --gap: 0; + } +} + +.search__controls, +.search__input { grid-column: 1 / -1; grid-row: 1 / -1; } @@ -19,16 +33,24 @@ display: block; box-sizing: border-box; width: 100%; + height: calc(1em + 1px); border: 0; - padding: 0 10px; + padding: 0 100px 0 10px; font: inherit; - letter-spacing: inherit; + line-height: calc(1em + 1px); + letter-spacing: -0.08em; color: inherit; outline: none; border-bottom: 2px solid hsl(0 0% 70%); background-color: transparent; } +@media (width >= 1024px) { + .search__input { + padding-inline-start: 0; + } +} + .search__input:focus { border-bottom-color: var(--color-text); } @@ -36,6 +58,7 @@ .search__control { position: relative; display: grid; + font-size: var(--font-size-l); } .search__control > * { @@ -51,12 +74,11 @@ } .search__key { - margin: 0 10px; place-self: center end; pointer-events: none; } -.search__input:focus ~ .search__key--activate { +.search__input:focus ~ .hotkey--search { visibility: hidden; } diff --git a/src/styles/blocks/standalone-page.css b/src/styles/blocks/standalone-page.css index df1a2cda..be838748 100644 --- a/src/styles/blocks/standalone-page.css +++ b/src/styles/blocks/standalone-page.css @@ -12,7 +12,7 @@ .standalone-page__header { padding: var(--offset); padding-top: clamp(20px, 8%, 130px); - border-bottom: 1px solid hsl(var(--color-base-text) / 0.3); + border-bottom: 1px solid var(--color-border); } .standalone-page__title { diff --git a/src/styles/blocks/subscribe-page.css b/src/styles/blocks/subscribe-page.css index 5f438c8a..14e1a975 100644 --- a/src/styles/blocks/subscribe-page.css +++ b/src/styles/blocks/subscribe-page.css @@ -9,7 +9,7 @@ padding: var(--gap); font-size: 24px; accent-color: hsl(var(--color-base-text)); - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); } .subscribe-settings__row--hidden { @@ -105,7 +105,7 @@ .unsubscribe-section { display: grid; margin-block-start: calc(var(--gap) * 2); - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); } .unsubscribe-section--hidden { diff --git a/src/styles/blocks/table-wrapper.css b/src/styles/blocks/table-wrapper.css index f91c63ed..527b4034 100644 --- a/src/styles/blocks/table-wrapper.css +++ b/src/styles/blocks/table-wrapper.css @@ -10,7 +10,7 @@ .table-wrapper > table td { text-align: start; padding: 0.25em 0.5em; - border: 1px solid var(--color-fade); + border: 1px solid hsl(var(--color-fade)); } .table-wrapper > table thead th { @@ -24,5 +24,5 @@ position: absolute; z-index: -1; inset: 0; - background-color: var(--color-fade); + background-color: hsl(var(--color-fade)); } diff --git a/src/styles/blocks/toc.css b/src/styles/blocks/toc.css index f86e59dd..5f8199f4 100644 --- a/src/styles/blocks/toc.css +++ b/src/styles/blocks/toc.css @@ -3,7 +3,13 @@ } .toc__item { - padding-left: 10px; + padding-inline-start: 10px; +} + +@media (width < 1024px) { + .toc__item:first-of-type { + padding-inline-end: 60px; + } } .toc__link { @@ -26,6 +32,12 @@ } .toc__link--active { - text-decoration: none; - background-color: var(--active-link-background, var(--color-fade)); + background-color: transparent; +} + +@media (width >= 1024px) { + .toc__link--active { + text-decoration: none; + background-color: var(--active-link-background, hsl(var(--color-fade))); + } } diff --git a/src/styles/dark-theme.css b/src/styles/dark-theme.css index 3ee82912..3ff6d32a 100644 --- a/src/styles/dark-theme.css +++ b/src/styles/dark-theme.css @@ -12,7 +12,8 @@ --color-text: hsl(var(--color-light)); --color-background: hsl(var(--color-dark)); - --color-fade: hsl(220 7% 25%); + --color-fade: 220 7% 28%; + --color-border: hsl(var(--color-base-text) / 0.3); --color-html: hsl(25 70% 24%); --color-css: hsl(209 70% 24%); diff --git a/src/styles/index.css b/src/styles/index.css index b633d054..8c95ca1e 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -15,9 +15,10 @@ @import url("blocks/logo.css"); @import url("blocks/hotkey.css"); @import url("blocks/breadcrumbs.css"); -@import url("blocks/menu-toggle.css"); +@import url("blocks/header-button.css"); @import url("blocks/header.css"); @import url("blocks/nav-list.css"); +@import url("blocks/header-animation.css"); @import url("blocks/search.css"); @import url("blocks/footer.css"); @import url("blocks/theme-toggle.css"); diff --git a/src/styles/index.sc.css b/src/styles/index.sc.css index 3a569111..debe3370 100644 --- a/src/styles/index.sc.css +++ b/src/styles/index.sc.css @@ -15,9 +15,10 @@ @import url("blocks/logo.css"); @import url("blocks/hotkey.css"); @import url("blocks/breadcrumbs.css"); -@import url("blocks/menu-toggle.css"); +@import url("blocks/header-button.css"); @import url("blocks/header.css"); @import url("blocks/nav-list.css"); +@import url("blocks/header-animation.css"); @import url("blocks/search.css"); @import url("blocks/footer.css"); @import url("blocks/theme-toggle.css"); diff --git a/src/styles/light-theme.css b/src/styles/light-theme.css index 7d5704e3..61aca53d 100644 --- a/src/styles/light-theme.css +++ b/src/styles/light-theme.css @@ -10,7 +10,8 @@ --color-text: hsl(var(--color-dark)); --color-background: hsl(var(--color-light)); - --color-fade: hsl(0 0% 92%); + --color-fade: 0 0% 82%; + --color-border: hsl(var(--color-base-text) / 0.3); --color-html: hsl(var(--color-orange)); --color-css: hsl(var(--color-blue)); diff --git a/src/views/404.njk b/src/views/404.njk index e2722cc5..e96e14d6 100644 --- a/src/views/404.njk +++ b/src/views/404.njk @@ -3,7 +3,7 @@ {{ header(isLogoImageHidden=true) }} - + diff --git a/src/views/article-index.njk b/src/views/article-index.njk index 59410889..1de77836 100644 --- a/src/views/article-index.njk +++ b/src/views/article-index.njk @@ -18,7 +18,7 @@ {{ categoryName }} - + {{ articleIndex.templateContent | safe }} @@ -26,7 +26,7 @@ {# fieldset и legend не работают с flexbox/grid #} Сортировать по: - Сортировать по: + Сортировать по: @@ -40,7 +40,7 @@ - + Статьи раздела «{{ categoryName }}» по темам diff --git a/src/views/doc.njk b/src/views/doc.njk index 6bd805d6..9dc3afcc 100644 --- a/src/views/doc.njk +++ b/src/views/doc.njk @@ -27,10 +27,10 @@ {{ categoryName }} - / + / - + {{ title | descriptionMarkdown | safe }} @@ -59,17 +59,26 @@ - - - Открыть/закрыть навигацию по статье - - - - - - - - + + + + Содержание + + + + + + + + + + +
$1