Центрируйте DIV неравномерно, используя CSS

23

Я центрирую DIV внутри другого DIV, используя flexbox. Подумайте о диалоговом окне, которое появляется в центре экрана при необходимости.

Это работает нормально, однако выглядело бы намного лучше, если бы пространство над и под диалоговым окном было не совсем одинаковым, с 40% оставшегося пространства над и 60% под диалоговым окном. Это становится сложно, потому что высота диалога зависит от количества текста внутри.

Например, если высота браузера составляет 1000 пикселей, а высота диалогового окна - 400 пикселей, я хочу, чтобы оставшееся вертикальное пространство (600 пикселей) было на 240 пикселей выше и на 360 пикселей ниже диалогового окна. Я мог бы сделать это с помощью Javascript, но мне любопытно, есть ли какой-нибудь умный способ с CSS. Я попытался добавить нижнее поле для #dialogBox DIV, но это не работает, когда высота диалога приближается к высоте браузера.

#dialogBoxPanel
  {
  position:absolute;
  display:flex;
  align-items:center;
  justify-content:center;
  left:0px;
  top:0px;
  width:100%;
  height:100%;
}
#dialogBox
  {
  width:350px;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Text</div>
</div>

Бьорн Морен
источник
Вам нужна внешняя панель, чтобы покрыть весь видовой экран? Если нет, я бы пошел с решением из css-tricks.com/centering-css-complete-guide , раздел «По горизонтали и вертикали / Является ли элемент неизвестной ширины и высоты?», И изменил бы значения перевода в процентах. (И даже если вам нужен родительский полный размер области просмотра [фон?], Вы должны иметь возможность комбинировать и то и другое - покончить с гибкими вещами, отдыхайте.)
04FS
Да, у меня есть эффект затемнения на внешней панели, поэтому он должен покрывать весь видовой экран. Но я могу добавить еще один DIV, и ваше решение будет работать нормально. Спасибо 04FS!
Бьорн Морен
Ради точности вы говорите о вертикальном выравнивании, а не о центрировании.
Майкл Бенджамин

Ответы:

11

Используйте псевдоэлемент и направление столбца для имитации пробела. Просто настройте flex-growпсевдоэлемент, чтобы контролировать, сколько свободного места должно занимать каждый. Равный flex-grow даст равное пространство:

Вы также можете использовать 2и 3. Нам просто нужно сохранить такое же соотношение:

Другая идея состоит в том, чтобы использовать верхнее значение, равное 40%и исправить положение с помощью translate (та же логика, что и 50%при центрировании)

#dialogBoxPanel {
  position: absolute;;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  /* the center */
  background:linear-gradient(red,red) center/100% 1px no-repeat;
}

#dialogBox {
  position:relative;
  top:40%;
  width: 350px;
  transform:translateY(-40%);
  margin:auto;
  border:1px solid;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>

Темани Афиф
источник
Большое спасибо, Темани! Оба решения работают идеально и выглядят одинаково, за исключением особого случая, когда диалог выше, чем браузер. Первое решение поддерживает верхнюю часть диалогового окна в верхней части браузера, обрезая ее в нижней части. Второй урожай как снизу, так и сверху. Просто вопрос предпочтений.
Бьорн Морен
5

Это решение использует display: grid, это новая функция, поэтому обязательно проверьте поддержку браузера и нажмите здесь, чтобы узнать больше.

Эта строка управляет верхним и нижним пространством:

grid-template-rows: 40fr [content-start] auto [content-end] 60fr;

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

#dialogBoxPanel {
    display: grid;
    place-content: center;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    grid-template-rows: 40fr [content-start] auto [content-end] 60fr;
}
#dialogBox {
    border: 1px solid;
    width: 350px;
    grid-area: content;
}
<div id="dialogBoxPanel">
   <div id="dialogBox" contenteditable>Text</div>
</div>

rafaelcastrocouto
источник
1
Я бы рассмотрел использование 4fr auto 6fr. То, что у вас работает, но с некоторым переполнением, так как 40% + 60% + 1fr всегда будет больше, чем 100%, и вы центрируетесь, поэтому наложение будет разделено поровну сверху и снизу: jsfiddle.net/cobutn0e/2 . Вы также заметите , что это не 100% , как ожидалось
Феманитян Afif
Я просто изменил 1fr на auto, я бы предпочел оставить его как%, чтобы соответствовать значениям вопроса. Большое спасибо за указание на ошибку!
rafaelcastrocouto
auto и 1fr дают одинаковый результат в вашем случае, проблема заключается в использовании процентов; 1fr=minmax(auto,1fr)и в вашем случае она упадет , autoпоскольку нет ни одного свободного места , так как 40% + 60% = 100% (именно поэтому у вас всегда будет переполнение)
Феманитяне Afif
1
вот еще скрипка , чтобы проиллюстрировать мою точку зрения: jsfiddle.net/cobutn0e/3 уведомления , как 3 первых такой же, третий один падает до 0 , а последний из которых является то , что я предложил
Феманитяне Afif
Теперь я понял, имеет смысл. Собираюсь использовать 40fr и 60fr, так как это то же самое в конце дня. Еще раз спасибо, что нашли время, чтобы научить меня!
rafaelcastrocouto
4

Вы можете добавить разделители div и установить flex-grow с соотношением 4: 6.

#dialogBoxPanel {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;

  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
}

#dialogBox {
  width: 350px;
  border: 1px solid black;
}

.spacer-top{
  flex-grow: 4;
}
.spacer-bottom{
  flex-grow: 6;
<div id="dialogBoxPanel">
  <div class="spacer-top"></div>
  <div id="dialogBox">Text</div>
  <div class="spacer-bottom"></div>
</div>

Итай Гал
источник
Только сейчас увидел ответ @Temani Afif, но он работает одинаково с «после» и «до»
Итай Гал
0

Простой способ с использованием позиции и поля, я предположил, что высота вашего диалога всегда составляет 40% от высоты браузера.

.modal{
            max-height:50%;
            width:400px;
            margin: 10% auto 5% auto;
            position:absolute;
            top:0;
            bottom:0;
            right:0;
            left:0;
            overflow-y: auto
        }
        .modal-body{
            background-color: beige;
            padding: 20px;
            line-height: 21px
        }

HTML

<div class="modal">
 <div class="modal-body">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. 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 </div>
</div>
Аншул Чаурасия
источник
Привет, добро пожаловать, в следующий раз, пожалуйста, внимательно прочитайте вопрос, он гласит: «Высота диалога зависит от количества текста внутри».
rafaelcastrocouto
1
@rafaelcastrocouto - теперь управление им через максимальную высоту в процентах, так как оставление без высоты не решит задачи эстетики верхнего и нижнего пространства.
Anshul Chaurasia