Макет сайта с двумя фиксированными сайдбарами по краям окна

Нtml-разметка для макета:
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">

  <link rel="stylesheet" href="style.css">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

  <link rel="canonical" href="https://site.com">

  <title>Title</title>
  <meta name="description" content="Description of the page content.">
</head>
<body>

<header id="header">
  <button id="button-left" onclick="navMainOpen()"><i class="material-icons md-light">apps</i></button>
  <a href="/" title="To main page">
    <img src="logo.png" alt="Logo of the website" width="30" height="30">
    <span>Site Name</span>
    <span id="subtitle">Short description of the website</span>
  </a>
  <button id="button-right" onclick="navSectionOpen()"><i class="material-icons md-light">menu</i></button>
</header>

<div id="main-overlay" onclick="navMainClose()"></div>
<div id="section-overlay" onclick="navSectionClose()"></div>

<nav id="main-sidebar" style="background:lightsteelblue;">
  <p>Теория</p>
  <ul>
    <li><a href="#">Начала программирования</a></li>
    <li><a href="#">Функции</a></li>
    <li><a href="#">...</a></li>
  </ul>
  <p>Задачи по темам</p>
  <ul>
    <li><a href="#">Линейные алгоритмы</a></li>
    <li><a href="#">Условные операторы</a></li>
    <li>...</li>
  </ul>
  <p>...</p>
</nav>

<main style="background:#f0f0f0;">
  <h1>Title of Article</h1>
  <p>Line 1</p><p>...</p>
</main>

<nav id="section-sidebar" style="background:lightgoldenrodyellow;">
  <header class="center">
    Задачи на массивы
  </header>
  <ul>
    <li><a href="#">Сумма и произведение элементов одномерного массива</a></li>
    <li><a href="#">Сумма положительных элементов массива</a></li>
    <li><a href="#">...</a></li>
  </ul>
</nav>

<footer style="background:lightskyblue;height:40px;text-align:center;padding-top:20px;">Flask.Website © 2025</footer>
<script src="script.js"></script>
</body>
</html>
Стилевая таблица заголовка и его компонентов в файле style.css:
body {
    margin: 0;
}
#header {
    position: fixed;
    top: 0px;
    width: 100%;
    height: 48px;
    padding: 2px;
    background: dodgerblue;
    transition: top 0.3s ease 0s;
    text-align: center;
}
#header a {
    text-decoration: none;
}
#header span {
    font-size: 24px;
    color: white;
}
#header #subtitle {
    display: none;
}
#header img {
    padding-right: 5px;
    padding-top: 7px;
    vertical-align: -5px;
}
#button-right, #button-left {
    cursor: pointer;
    margin-top: 6px;
    width: 36px;
    height: 36px;
    font-size: 32px;
    background: white;
    border: none;
}
#button-right {
    float: right;
    margin-right: 10px;
}
#button-left {
    float: left;
    margin-left: 5px;
}
@media (min-width: 1351px) {
    #button-left, #button-right {
        display: none;
    }
    #header {
        text-align: left;
        padding: 0;
        width: 300px;
        height: 100px;
    }
    #header img {
        padding: 15px 10px 10px 30px;
        vertical-align: -15px;
    }
    #header #subtitle {
        display: block;
        font-size: 18px;
        padding-left: 30px;
    }
}

На больших экранах заголовок имеет ширину левого сайдбара и окажется над ним. И на широких, и на узких экранах заголовку задается фиксированная позиция с помощью css-свойства position. Однако на узких экранах заголовок будет исчезать при прокрутке вниз и появляться сразу при небольшой прокрутке вверх, отображая тем самым расположенные на нем кнопки, открывающие сайдбары. Такое поведение задается с помощью JS.

Код, управляющий видимостью заголовка при прокрутке на узких экранах, в файле script.js:
function checkMedia(media) {
    var header = document.getElementById("header");
    var prevScrollpos = window.pageYOffset;
    window.onscroll = function() {
        var currentScrollPos = window.pageYOffset;
        if (prevScrollpos > currentScrollPos) {
            header.style.top = "0";
        } else {
            if (media.matches) {
                header.style.top = "-95px";
            } else {
                header.style.top = "0";
            }
        }
        prevScrollpos = currentScrollPos;
    }
}

var m = window.matchMedia("(max-width: 1350px)");
checkMedia(m);
m.addListener(checkMedia);
CSS-правила левого сайдбара:
#main-sidebar {
    display: none;
    position: fixed;
    top: 0;
    bottom: 0;
    width: 300px;
    overflow: auto;
}
@media (min-width: 1351px) {
    #main-sidebar {
        display: block!important;
        top: 100px;
    }
}

На широких экранах сверху делается отступ в ширину заголовка (100px).

CSS-правила правого сайдбара:
#section-sidebar {
    display: none;
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    width: 300px;
}
#section-sidebar header {
    border-bottom: 1px solid lightgray;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
}
#section-sidebar ul {
    position: fixed;
    top: 50px;
    bottom: 0px;
    overflow: auto;
    margin-top: 0;
    padding-top: 10px;
}
@media (min-width: 1351px) {
    #section-sidebar {
        display: block!important;
    }
    #section-sidebar header {
        height: 100px;
        font-size: 1.5em;
    }
    #section-sidebar ul {
        top: 100px;
    }
}

В данном случае все немного сложнее, потому что внутри фиксированного сайдбара мы делаем фиксированный хэдер (заголовок меню). Он не будет исчезать при скроллинге меню, и правая панель будет похожа на левую.

Если раскрытие сайдбаров на узких экранах обеспечивается с помощью кнопок, то закрытие - с помощью "оверлеев".

CSS-правило оверлеев:
#main-overlay, #section-overlay {
    display: none;
    position: fixed;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.5);
}
JS-код, открывающий и закрывающий сайдбары, в файле script.js:
function navMainOpen() {
    document.getElementById("main-sidebar").style.display = "block";
    document.getElementById("main-overlay").style.display = "block";
}
function navMainClose() {
    document.getElementById("main-sidebar").style.display = "none";
    document.getElementById("main-overlay").style.display = "none";
}

function navSectionOpen() {
    document.getElementById("section-sidebar").style.display = "block";
    document.getElementById("section-overlay").style.display = "block";
}
function navSectionClose() {
    document.getElementById("section-sidebar").style.display = "none";
    document.getElementById("section-overlay").style.display = "none";
}
Таблица стилей контейнера main:
main {
    padding: 55px 15px;
}
@media (min-width: 871px) {
    main {
        max-width: 840px;
        margin: 0 auto;
    }
}
@media (min-width: 1351px) {
    main {
        margin-left: 310px;
        margin-right: 310px;
        padding-top: 5px;
    }
    footer {
        margin-left: 300px;
        margin-right: 300px;
    }
}
@media (min-width: 1500px) {
    main {
        margin: 0 auto;
    }
}

Основное содержимое начинается сразу у верха страницы. Поэтому на узких экранах мы должны сделать отступ сверху на высоту заголовка, так как там он растянут на всю ширину окна.

Остальные CSS-правила макета:
#main-sidebar p {
    margin-left: 20px;
    font-size: 1.2em;
}
#main-sidebar ul {
    list-style-type: none;
    line-height: 1.7em;
}
#main-sidebar a {
    color: darkblue;
    text-decoration: none;
}

#section-sidebar ul {
    padding-inline-start: 30px;
}
#section-sidebar ul li {
    padding-bottom: 15px;
}

#main-sidebar::-webkit-scrollbar-track { background: lightsteelblue; }
#main-sidebar::-webkit-scrollbar-thumb { background: lightgrey; }
#main-sidebar::-webkit-scrollbar-thumb:hover { background: lightgrey;}
#main-sidebar::-webkit-scrollbar, #section-sidebar ul::-webkit-scrollbar { width: 7px; }
#section-sidebar ul::-webkit-scrollbar-track { background: lightgoldenrodyellow;}
#section-sidebar ul::-webkit-scrollbar-thumb { background: lightgray; }
#section-sidebar ul::-webkit-scrollbar-thumb:hover { background: lightgray; }