Как установить поле или отступ в процентах от высоты родительского контейнера?


236

Я ломал голову над созданием вертикального выравнивания в CSS, используя следующее

.base{
        background-color:green;
	    width:200px;
	    height:200px;
	    overflow:auto;
	    position:relative;
	}

    .vert-align{
		padding-top:50%;
		height:50%;
	}
<!-- and used the following div structure. -->

    <div class="base">
       <div class="vert-align">
    	   Content Here
       </div>
    </div>

Хотя в этом случае это работало, я был удивлен, что, когда я увеличивал или уменьшал ширину моего базового элемента div, вертикальное выравнивание зависало. Я ожидал, что когда я установлю свойство padding-top, он будет принимать отступ в процентах от высоты родительского контейнера, который в нашем случае является базовым, но указанное выше значение в 50 процентов рассчитывается как процент от ширина. :(

Есть ли способ установить отступы и / или поля в процентах от высоты, не прибегая к использованию JavaScript?

Ответы:


223

Исправление , что да, вертикальное заполнение и рентабельность по сравнению с шириной, но topи bottom не является.

Так что просто поместите div внутри другого, а во внутреннем div используйте что-то вроде top:50%(запомните, positionесли это все еще не работает)


3
topотлично работает для изменения размера в зависимости от высоты браузера / окна. Как насчет того, чтобы иметь div под этим div? Как вы можете clear2-й div быть под div, который сдвинут вниз top:50%?
Федерико

Учиться чему-то новому. Не знал, что вертикальные отступы и поля относительно ширины раньше. Спасибо.
Shaosh

5
Также возможно добавить div 'spacer' с заданной процентной высотой. Кажется немного грязным, но это работает. увидеть этот ответ .
WCByrne

4
Что вечно живущий @%! ^? Почему вертикальные поля и отступы относятся к ширине ? ЧТО? С какой стати это решение было принято?
temporary_user_name

Ваш ответ чрезвычайно непропорционально высоко оценен по сравнению с ответом Алена ниже, который дает общее решение, и я нашел его очень полезным и почти не видел его. top: 50%не очень полезно, если вам нужно выровнять содержимое по своему центру.
Оковко

35

Ответ на немного другой вопрос: Вы можете использовать vhединицы измерения, чтобы добавить элементы в центр области просмотра :

.centerme {
    margin-top: 50vh;
    background: red;
}

<div class="centerme">middle</div>

Почему за этот ответ не проголосовали выше? Что-то не так с использованием VH?
AlanH

3
Это потому, что это не ответ, адаптированный к исходному вопросу, а полезный прием, который работает только в нескольких связанных случаях.
Willoller

использование vhпочти такое же, как проценты ... еще хуже в некоторых случаях. Этот ответ не имеет отношения к вопросу
vsync

33

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

<div id="outer">
    <div id="inner">
        content
    </div>
</div>

Первый вариант: использовать псевдоэлементы, здесь вертикальный и горизонтальный интервалы относительно внешнего. демонстрация

#outer::before, #outer::after {
    display: block;
    content: "";
    height: 10%;
}
#inner {
    height: 80%;
    margin-left: 10%;
    margin-right: 10%;
}

Перемещение горизонтального промежутка к внешнему элементу делает его относительно родителя внешнего. демонстрация

#outer {
    padding-left: 10%;
    padding-right: 10%;
}

Второй вариант: использовать абсолютное позиционирование. демонстрация

#outer {
    position: relative;
}
#inner {
    position: absolute;
    left: 10%;
    right: 10%;
    top: 10%;
    bottom: 10%;
}

10

Чтобы сделать дочерний элемент абсолютно позиционированным относительно его родительского элемента, вам нужно установить относительную позицию на родительском элементе И абсолютную позицию на дочернем элементе.

Тогда на дочернем элементе 'top' относительно высоты родительского элемента. Поэтому вам также нужно «перевести» ребенка на 50% выше его собственного роста.

.base{
    background-color: green;
    width: 200px;
    height: 200px;
    overflow: auto;
    position: relative;
}
    
.vert-align {
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
}
    <div class="base">
        <div class="vert-align">
            Content Here
        </div>
    </div>

Существует еще одно решение с использованием flex box.

.base{
    background-color:green;
    width: 200px;
    height: 200px;
    overflow: auto;
    display: flex;
    align-items: center;
}
<div class="base">
    <div class="vert-align">
        Content Here
    </div>
</div>

Вы найдете преимущества / недостатки для обоих.


1
Использование translate является единственным реальным способом перемещения элемента по вертикали относительно его собственного размера.
Эран Голдин

Спасибо за это. Это должен быть выбранный ответ.
Вессам Эль Махди

6

Это может быть достигнуто с writing-modeсобственностью. Если вы установите для элемента writing-modeрежим вертикальной записи, например vertical-lr, процентные значения его потомков для отступов и полей в обоих измерениях станут относительными к высоте, а не к ширине.

Из спецификации :

, , , проценты на полях и свойствах заполнения, которые всегда рассчитываются относительно ширины содержащего блока в CSS2.1, рассчитываются относительно встроенного размера содержащего блока в CSS3.

Определение встроенного размера :

Измерение в линейном измерении: относится к физической ширине (горизонтальному измерению) в режимах горизонтальной записи и к физической высоте (вертикальному измерению) в режимах вертикальной записи.

Например, с изменяемым размером элемента, где горизонтальные поля относятся к ширине, а вертикальные поля - к высоте.

.resize {
  width: 400px;
  height: 200px;
  resize: both;
  overflow: hidden;
}

.outer {
  height: 100%;
  background-color: red;
}

.middle {
  writing-mode: vertical-lr;
  margin: 0 10%;
  width: 80%;
  height: 100%;
  background-color: yellow;
}

.inner {
  writing-mode: horizontal-tb;
  margin: 10% 0;
  width: 100%;
  height: 80%;
  background-color: blue;
}
<div class="resize">
  <div class="outer">
    <div class="middle">
      <div class="inner"></div>
    </div>
  </div>
</div>

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


Это, IMO, было бы более элегантным решением, но (по состоянию на 2018-05-05) режимы вертикальной записи плохо поддерживаются . Надеюсь, это скоро изменится.
zanerock

1
@zanerock Я уверен, что таблица сравнения MDN устарела. Например, в нем говорится, что Safari нужен -webkit-префикс, но, согласно caniuse, он не требует префикса с Safari 11. Пробовали ли вы его с любым браузером, в котором он не работал?
Джеймс Т

1
Нет, я должен признать, я просто предположил, что это было хорошо, даже автоматизировано.
Занерок

4

Другой способ центрировать одну строку текста:

.parent{
  position: relative;
}

.child{
   position: absolute;
   top: 50%;
   line-height: 0;
}

или просто

.parent{
  overflow: hidden; /* if this ins't here the parent will adopt the 50% margin of the child */
}

.child{
   margin-top: 50%;
   line-height: 0;
}

0

50% -ая обивка не отцентрирует вашего ребенка, она поместит его ниже центра. Я думаю, что вы действительно хотите верхний слой 25%. Может быть, вам просто не хватает места, поскольку ваш контент становится выше? Также вы пытались установить поле margin вместо top?

РЕДАКТИРОВАТЬ: Nevermind, сайт w3schools говорит

% Определяет заполнение в процентах от ширины содержащего элемента.

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

То, что вы делаете, может быть достигнуто с помощью display: table, хотя (по крайней мере, для современных браузеров). Техника объясняется здесь .


1
Спасибо, Сплиф. Я понимаю, что мои 50% не будут центрировать содержание div. На самом деле у меня есть только одна строка текста, которая должна быть центрирована вертикально. Большое спасибо за ссылку, хотя!
Райан

3
Если бы это была только одна строка текста, рассматривали ли вы использование смехотворно большого размера line-height, то есть сделать высоту строки 200 пикселей?
SpliFF

@Ryan для центрирования текста по вертикали, см. Stackoverflow.com/questions/8865458/…
пользователь

Ваша ссылка не работает
лету

0

Это очень интересная ошибка. (На мой взгляд, это все равно ошибка) Хорошая находка!

Относительно того, как установить это, я рекомендовал бы ответ Камило Мартина. Но почему , я бы хотел немного объяснить это, если вы, ребята, не против.


В спецификации CSS я нашел:


Процент заполнения : относится к ширине содержащего блока

... что странно, но хорошо.

Итак, с родителем width: 210pxи ребенком padding-top: 50%я получаю вычисленное / вычисленное значение padding-top: 96.5px- что не является ожидаемым 105px.

Это потому, что в Windows (я не уверен насчет других ОС), размер общих полос прокрутки по умолчанию 17px × 100%(или 100% × 17pxдля горизонтальных полос). Те 17pxвычитаются до расчета 50%, следовательно 50% of 193px = 96.5px.


Есть причина для спецификации, и это объясняет это лучше: hongkiat.com/blog/calculate-css-percentage-margins
manikanta
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.