Я хочу выполнить этот скрипт в рамках astro, чтобы настроить размещение нижнего колонтитула в конце страницы, если страница короче области просмотра (если есть лучший способ, сообщите мне, но здесь проблема не в этом):
window.onload = function () {
const footer = document.querySelector('footer')
if (!footer) return
const bodyHeight = document.body.clientHeight
const windowHeight = window.innerHeight
if (bodyHeight < windowHeight) {
footer.style.position = 'absolute'
footer.style.bottom = '0'
footer.style.width = '100%'
}
}
Но поскольку он асинхронный, document.body.clientHeight равен 0 9 раз по 10, а window.onload обработчик ничего не меняет. Я тоже пробовал body.onload, но то же самое.
Вот мое дерьмовое исправление:
window.onload = function () {
const footer = document.querySelector('footer')
if (!footer) return
footer.style.display = 'none'
setTimeout(function () {
const bodyHeight = document.body.clientHeight
const windowHeight = window.innerHeight
if (bodyHeight < windowHeight) {
footer.style.position = 'absolute'
footer.style.bottom = '0'
footer.style.width = '100%'
}
footer.style.display = 'block'
}, 100) // Let the page load first
}
@AnnaK Я пыталась установить минимальную высоту тела на 100vh, но это переместило все мои остальные компоненты, а с моей фактической конфигурацией CSS это беспорядок. Но более того, я хочу понять, как справиться с такого рода асинхронной проблемой.
То, чего вы хотите добиться, называется липким нижним колонтитулом. Подробнее можно прочитать здесь .
@iseven, конечно, в образовательных целях это нормально, но, честно говоря, это НЕ правильный способ делать такие вещи...
В настоящее время это выглядит как проблема XY. «Помогите мне подняться на верхний этаж здания, используя мои альпинистские ботинки», хотя ответом может быть «использовать лестницу».
@MarkSchultheiss Как я уже сказал, я знаю, что это неправильный путь, я просто хотел знать, как справиться с такой асинхронной проблемой



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вам не нужно использовать JavaScript для достижения этого эффекта. Взгляните на это, например:
function AddContentToExemple() {
const contentElement = document.querySelector("main");
contentElement.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum");
}:root {
--footer-height: 20px;
}
main {
min-height: calc(100vh - var(--footer-height));
padding: 40px 40px 0 40px;
box-sizing: border-box;
}
body {
margin: 0;
}
footer {
height: var(--footer-height);
background-color: red;
color: white;
}<main>
<p>You can add text by clicking on the button bellow :</p>
<button onclick = "AddContentToExemple()">Add Content</button>
</main>
<footer class = "footer">
Footer
</footer>Не уверен, что это решит вашу проблему, но сначала я бы попробовал использовать этот прослушиватель событий вместо window.onload:
document.addEventListener("DOMContentLoaded", (event) => {
console.info("DOM fully loaded and parsed");
});
ОП упоминает, что некоторый контент загружается асинхронно. Я не уверен, что DOMContentLoaded сработает, когда это завершится. (Я не минусовал, просто прокомментировал)
Я не знаю, как выглядит ваш CSS, кроме части JS:
Вы используете setTimeout, чтобы задержать выполнение вашей логики/функции.
Я бы рекомендовал использовать Promise.resolve().
Это аналогичная идея, но немного более элегантная, поскольку вместо ожидания произвольного времени, установленного в вашей функции setTimout, ее запуск запланирован на следующий цикл цикла событий после того, как все другие функции в трассировке стека вернутся.
Ваш код будет выглядеть так:
window.onload = function () {
const footer = document.querySelector('footer')
if (!footer) return
footer.style.display = 'none'
Promise.resolve(()=>{
const bodyHeight = document.body.clientHeight
const windowHeight = window.innerHeight
if (bodyHeight < windowHeight) {
footer.style.position = 'absolute'
footer.style.bottom = '0'
footer.style.width = '100%'
}
footer.style.display = 'block'
}
) // Let the page load first
}
Попробуй!
Так что это не поможет мне в асинхронной части, но вот мое исправление для нижнего колонтитула в CSS.
:root {
--header-height: 6.5rem;
--footer-height: 5rem;
}
main {
min-height: calc(100vh - var(--header-height) - var(--footer-height));
padding: 40px 40px 0 40px;
box-sizing: border-box;
}
Я просто добавляю основной макет в свой базовый макет Astro.
Поскольку я считаю, что реальной проблемой является создание макета верхнего/основного/нижнего колонтитула, это может быть намного проще, просто используя одну строку CSS. Комментарии в CSS, но первый раздел является ключом для контейнера для установки всех трех областей на основе дочернего содержимого верхнего и нижнего колонтитула, а основной получает все остальное.
.parent-container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
}
/* everthing below here is just to show what is where */
.section {
/* just to "super center" each section */
display: grid;
place-items: center;
}
.header.section {
background-color: #FF000020;
font-size: 2em;
height: 2em;
}
.main.section {
background-color: #00FF0020;
}
.footer.section {
background-color: #0000FF20;
height: 3em;
}<div class = "parent-container">
<div class = "header section" contenteditable>Header</div>
<div class = "main section" contenteditable>Main</div>
<div class = "footer section" contenteditable>Footer Content</div>
</div>
Пробовали ли вы добиться того же результата, используя только правила CSS и не устанавливая абсолютное положение нижнего колонтитула? Просто интересуюсь.