Как убедиться, что тело имеет высоту перед запуском скрипта

Я хочу выполнить этот скрипт в рамках 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
    }

Пробовали ли вы добиться того же результата, используя только правила CSS и не устанавливая абсолютное положение нижнего колонтитула? Просто интересуюсь.

AnnaK 03.04.2024 16:34

@AnnaK Я пыталась установить минимальную высоту тела на 100vh, но это переместило все мои остальные компоненты, а с моей фактической конфигурацией CSS это беспорядок. Но более того, я хочу понять, как справиться с такого рода асинхронной проблемой.

ISEVEN 03.04.2024 16:43

То, чего вы хотите добиться, называется липким нижним колонтитулом. Подробнее можно прочитать здесь .

Invulner 03.04.2024 16:55

@iseven, конечно, в образовательных целях это нормально, но, честно говоря, это НЕ правильный способ делать такие вещи...

AnnaK 03.04.2024 16:55

В настоящее время это выглядит как проблема XY. «Помогите мне подняться на верхний этаж здания, используя мои альпинистские ботинки», хотя ответом может быть «использовать лестницу».

Mark Schultheiss 03.04.2024 17:15

@MarkSchultheiss Как я уже сказал, я знаю, что это неправильный путь, я просто хотел знать, как справиться с такой асинхронной проблемой

ISEVEN 07.04.2024 19:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
81
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вам не нужно использовать 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 сработает, когда это завершится. (Я не минусовал, просто прокомментировал)

GetSet 03.04.2024 17:12

Я не знаю, как выглядит ваш 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>

Другие вопросы по теме