Нужно чуть больше контекста (прикрепите макет или опишите, какие именно элементы и как должны зависеть от высоты), но в общем случае есть несколько надёжных подходов — от чисто CSS до небольшого JS-скрипта. Ниже — практичные варианты, которые работают в старых окружениях, где Flexbox доступен, а Grid нежелателен.
Коротко:
- Для того чтобы процентная высота работала, у родителя должна быть задана явная высота (px, vh или % от родителя с установленной высотой).
- Flexbox удобен для распределения по высоте: flex-direction: column и flex: N позволяют задавать пропорции высот.
- Если вам нужно рассчитывать размеры (в т.ч. ширины или шрифты) на основе текущей высоты контейнера — надёжно делать это через небольшой JS, который вычисляет «единицу» по высоте и устанавливает стили/переменные.
1) Чисто CSS (если достаточно пропорций по высоте)
- Сценарий: у вас есть контейнер высотой 100vh, внутри — header (фикс), footer (фикс) и контент, который занимает остальную высоту; в контенте блоки делятся по высоте пропорционально.
Пример:
html, body { height: 100%; margin: 0; }
.container { height: 100vh; display: flex; flex-direction: column; }
.header { height: 60px; }
.footer { height: 40px; }
.content { flex: 1; display: flex; flex-direction: column; }
.block-a { flex: 2; } /* займёт 2 части из 3 */
.block-b { flex: 1; } /* займёт 1 часть */
Пояснение: flex задаёт относительные высоты. Для процентов: .container должна иметь фиксированную высоту (100vh или px), тогда дочерние height: 50% будут работать.
2) Если нужно задавать размеры элементов напрямую «из высоты» (например, ширина/шрифт/отступы должны быть пропорциональны высоте контейнера)
- Рекомендация: вычислить базовую единицу на JS и записать в CSS-переменную или в inline-стили. Это даёт совместимость с более старыми браузерами — если CSS-переменные недоступны, можно прямо выставить style.width/height/fontSize.
Пример (без использования CSS-переменных, максимально совместимо):
<script>
function applySizeByHeight() {
var root = document.getElementById('wrap'); // контейнер
var h = root.clientHeight; // высота в px
var unit = h / 12; // допустим делим на 12
// применяем к элементам
var els = document.querySelectorAll('.byHeight');
for (var i=0;i<els.length;i++){
els[i].style.height = Math.round(unit * (els[i].dataset.h||1)) + 'px';
els[i].style.width = Math.round(unit * (els[i].dataset.w||2)) + 'px';
// можно менять и fontSize: els[i].style.fontSize = Math.round(unit*0.3)+'px';
}
}
window.addEventListener('load', applySizeByHeight);
window.addEventListener('resize', applySizeByHeight);
</script>
HTML:
<div id="wrap" style="height:80vh">
<div class="byHeight" data-h="3" data-w="4">Блок</div>
...
</div>
Пояснение: вы рассчитываете «unit» от реальной высоты контейнера и применяете к элементам. Это даёт точный контроль, кроссбраузерно работает даже в старых IE (если они поддерживают JS и Flexbox).
3) Использование vh/viewport-единиц
- Если можно ориентироваться на высоту окна, vh — простое решение: height: 10vh; font-size: 2vh; margin: 1vh;
- Поддержка: IE9+ имеет базовую поддержку vh. Для старых браузеров на XP — может не работать в очень старых версиях, поэтому проверяйте.
4) Практический паттерн: фиксированный макет с колонками, размеры по высоте
- Если, например, у вас есть схема «левое меню» — содержимое — правый сайдбар, но ширина колонок должна зависеть от высоты окна (редко, но бывает) — нужно вычислять ширину через JS на основе контейнера.clientHeight и выставлять style.width.
Советы по совместимости:
- Для процентов высоты всегда убедитесь, что все верхние контейнеры имеют явную высоту (html, body, #app — height:100%).
- CSS-переменные (var(--x)) удобны, но не поддерживаются в старых браузерах. Для максимальной совместимости используйте JS, который записывает inline-стили.
- Flexbox — хорош; используйте старые префиксы, если целевая версия браузера очень старая (-ms- для старых IE с 2012-era флексом — но вы сказали, что Flex работает, значит, возможно, это не нужно).
- Для плавной адаптации при изменении размеров слушайте resize и пересчитывайте.
Если приложите макет (изображение или ASCII-схему) — я покажу готовый пример кода (HTML+CSS и, при необходимости, небольшой JS), точно под вашу структуру. Хотите чисто CSS-решение или может быть JS-решение для точного расчёта?