Переполнение гибкого элемента в направлении главной оси

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

Я хотел бы создать элемент overlay с элементами управления для элемента display, где элементы управления расположены вертикально и выровнены по правому и нижнему краю экрана. Существует один элемент фиксированного размера buttons, содержащий некоторые элементы управления, а затем элемент динамического размера info, который появляется только тогда, когда некоторые части дисплея активны. info всегда содержит кнопку закрытия и некоторую информацию о динамической высоте. Я бы хотел, чтобы контейнер info всегда сжимался до своего содержимого. Однако, если высота содержимого слишком велика и содержащий элемент info будет выше, чем оставшееся вертикальное пространство контейнера overlay, я бы хотел, чтобы содержимое можно было прокручивать.

Я думал, что просто использую гибкий контейнер и атрибуты overflow-y, но, похоже, это не поможет. Кажется, что переполнение срабатывает только в том случае, если родительский контейнер имеет определенную высоту, но в моем случае родительский контейнер является динамическим, то есть он должен расти до определенной высоты, а затем останавливаться, пока содержимое становится прокручиваемым.

Это была моя попытка:

const info = document.querySelector(".info");
const content = document.querySelector(".content");

document.querySelector("#open-info").addEventListener("click", () => {
  info.style.display = "flex";
});

document.querySelector("#close-info").addEventListener("click", () => {
  info.style.display = "none";
});

document.querySelector("#increase-height").addEventListener("click", () => {
  content.style.height = `${content.clientHeight + 30}px`;
});

document.querySelector("#decrease-height").addEventListener("click", () => {
  content.style.height = `${content.clientHeight - 30}px`;
});
.display {
  position: relative;
  width: 400px;
  height: 300px;
  background-color: gray;
}

.overlay {
  position: absolute;
  display: flex;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
}

.info {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
  flex-shrink: 0;
  background-color: orange;
  padding: 10px;
  max-height: 230px;
  /* overflow works, but fixed size is undesirable, as the remaining space in main-axis direction should be used up */
  /* max-height: 100%; overflow doesn't work, as it refers to parent's height, not to remaining available space in main-axis direction*/
}

.info-content-wrapper {
  padding: 5px;
  overflow-x: hidden;
  overflow-y: auto;
}

.content {
  width: 80px;
  height: 150px;
  background-color: yellow;
}

.controls {
  background-color: lightblue;
  padding: 5px;
  flex: 0 0 auto;
}
<div class = "display">
  <div class = "overlay">
    <div class = "info">
      <button id = "close-info">Close</button>
      <div class = "info-content-wrapper">
        <div class = "content"></div>
      </div>
    </div>
    <div class = "controls">
      <button id = "open-info">Open info</button>
      <button id = "increase-height">+</button>
      <button id = "decrease-height">-</button>
    </div>
  </div>
</div>

В примере вы можете использовать кнопки, чтобы скрыть/показать информацию, а также увеличить/уменьшить высоту контента. Я использовал фиксированный max-height: 230px на .info, чтобы продемонстрировать, как это должно работать. Однако вместо использования фиксированного max-height следует использовать оставшееся вертикальное пространство гибкого контейнера. Но когда я использую max-height: 100%, он (согласно определению) будет относиться к общей высоте родительского гибкого контейнера. Если я вложу его дальше (например, внедрив обертку вокруг внутреннего HTML .info) и установлю max-height этого элемента на 100%, это все равно не сработает.

Мне кажется, что ответ должен быть очень простым, но я не могу найти решение, используя только гибкую компоновку и не прибегая к обходным путям с помощью calc. Я чувствую себя очень глупо по этому поводу и был бы очень рад помощи!

Не могли бы вы уточнить, является ли элемент <div class = "content"> просто примером заполнителя для самого контента? Другими словами, должно ли что-либо, содержащееся в <div class = "info-content-wrapper">, быть прокручиваемым, или реальный контент должен быть вложен в элемент <div class = "content">?

Invulner 17.04.2024 17:54
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
2
1
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я скомпилировал этот фрагмент кода, который вы можете попробовать:

<!DOCTYPE html>
<html lang = "en">
<head>
    <meta charset = "UTF-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
    <style>
        .display {
            position: relative;
            width: 400px;
            height: 300px;
            background-color: gray;
        }

        .overlay {
            position: absolute;
            display: flex;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
            flex-direction: column;
            justify-content: flex-end;
            align-items: flex-end;
        }

        .info {
            display: none; /* Initially hidden */
            flex-shrink: 0;
            background-color: orange;
            padding: 10px;
            max-height: 230px; /* Shrink to content */
        }

        .info-content-wrapper {
            padding: 5px;
            overflow-y: auto; /* Scrollable if content exceeds height */
        }

        .content {
            width: 80px;
            height: 150px;
            background-color: yellow;
        }

        .controls {
            background-color: lightblue;
            padding: 5px;
            flex: 0 0 auto;
        }
    </style>
</head>
<body>
    <div class = "display">
        <div class = "overlay">
            <div class = "info">
                <button id = "close-info">Close</button>
                <div class = "info-content-wrapper">
                    <div class = "content"></div>
                </div>
            </div>
            <div class = "controls">
                <button id = "open-info">Open info</button>
                <button id = "increase-height">+</button>
                <button id = "decrease-height">-</button>
            </div>
        </div>
    </div>

    <script>
        const info = document.querySelector(".info");
        const content = document.querySelector(".content");

        document.querySelector("#open-info").addEventListener("click", () => {
            info.style.display = "flex";
        });

        document.querySelector("#close-info").addEventListener("click", () => {
            info.style.display = "none";
        });

        document.querySelector("#increase-height").addEventListener("click", () => {
            content.style.height = `${content.clientHeight + 30}px`;
        });

        document.querySelector("#decrease-height").addEventListener("click", () => {
            content.style.height = `${content.clientHeight - 30}px`;
        });
    </script>
</body>
</html>

Спасибо за фрагмент! К сожалению, он ведет себя не совсем так, как мне хотелось, потому что контейнер .info не должен иметь фиксированного max-height, а вместо этого использовать оставшееся вертикальное пространство.

panda-byte 18.04.2024 10:29
Ответ принят как подходящий

Просто удалите .info { flex-shrink: 0; } и добавьте .info { overflow: hidden; } или .info { min-height: 0 }, чтобы сделать этот блок сжимаемым:

const info = document.querySelector(".info");
const content = document.querySelector(".content");

document.querySelector("#open-info").addEventListener("click", () => {
  info.style.display = "flex";
});

document.querySelector("#close-info").addEventListener("click", () => {
  info.style.display = "none";
});

document.querySelector("#increase-height").addEventListener("click", () => {
  content.style.height = `${content.clientHeight + 30}px`;
});

document.querySelector("#decrease-height").addEventListener("click", () => {
  content.style.height = `${content.clientHeight - 30}px`;
});
.display {
  position: relative;
  width: 400px;
  height: 300px;
  background-color: gray;
}

.overlay {
  position: absolute;
  display: flex;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
}

.info {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
  /* flex-shrink: 0; */
  background-color: orange;
  padding: 10px;
  /* max-height: 230px; */
  overflow: hidden;
}

.info-content-wrapper {
  padding: 5px;
  overflow-x: hidden;
  overflow-y: auto;
}

.content {
  width: 80px;
  height: 150px;
  background-color: yellow;
}

.controls {
  background-color: lightblue;
  padding: 5px;
  flex: 0 0 auto;
}
<div class = "display">
  <div class = "overlay">
    <div class = "info">
      <button id = "close-info">Close</button>
      <div class = "info-content-wrapper">
        <div class = "content"></div>
      </div>
    </div>
    <div class = "controls">
      <button id = "open-info">Open info</button>
      <button id = "increase-height">+</button>
      <button id = "decrease-height">-</button>
    </div>
  </div>
</div>

Спасибо большое, похоже это именно то, что мне нужно! По какой-то причине я не думал, что дело в способности .info сжиматься, хотя в ретроспективе это кажется совершенно очевидным. Спасибо!

panda-byte 18.04.2024 10:28

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