Підтримуйте співвідношення сторін зображення при зміні висоти


114

Використовуючи модель CSS flex box, як я можу змусити зображення підтримувати його співвідношення сторін?

JS Fiddle: http://jsfiddle.net/xLc2Le0k/2/

Зауважте, що зображення розтягуються або зменшуються, щоб заповнити ширину контейнера. Це добре, але чи можемо ми його також розтягнути або зменшити висоту, щоб зберегти пропорції зображення?

HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}

1
Наскільки я знаю, найкращим рішенням є використання <div>CSSbackground-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger

1
Тут є кілька цікавих підстав, але як бути, коли зображення вже не мають однакового співвідношення? Додавання та "додатковий" поділ - це останнє, про що ми повинні турбуватися. Чому б не використати тестовий приклад , як це замість: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

Відповіді:


68

Для тегів img, якщо ви визначаєте одну сторону, то інша сторона змінює розмір, щоб зберегти співвідношення сторін, а зображення за замовчуванням розширити до початкового розміру.

Використовуючи цей факт, якщо ви загортаєте кожен тег img у тег div та встановлюєте його ширину на 100% від батьківського div, то висота буде залежати від пропорції, як ви хотіли.

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}

2
Я знаю, що є дві відповіді, які пропонують використовувати divs, але я відзначаю цю відповідь правильною, оскільки вона пояснює, чому висота зображення відрізняється, ніж я очікував. Насправді це нормальна та правильна поведінка, і навряд чи це буде «виправлено», оскільки це не помилка.
coderMe

18
Але ця відповідь нічого не говорить про flexbox, оскільки зображення поводяться по-різному в контейнері flexbox. Встановлення однієї сторони пропорційно не змінить розмір іншої. Обгортання їх у контейнер, який не є flexbox, допомагає, але це додає зайвої розмітки, втрачаючи семантичність.
Роберт Коритник

3
Не здається, що вам потрібен розгортаючий дів,
Rick Strahl

4
Але, що з цим? jsfiddle.net/xLc2Le0k/15 Я думаю, що це рішення - це флюйк, який працює лише тому, що зображення мають однакове співвідношення. бічна примітка: немає жодної «семантичності», втраченої при розміщенні зображення в діві для позиціонування / особливо при роботі із чуйними зображеннями.
шерифдерек

1
Серйозно найчистіше рішення, і воно працює з малюнком!
shaneonabike

64

Щоб зображення не розтягувались по будь-якій осі всередині гнучкої батьківки, я знайшов пару рішень.

Ви можете спробувати скористатися об'єктом на зображенні, яке, наприклад

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Або ви можете додати специфічні правила, які можуть працювати краще в деяких випадках.

align-self: center;
flex: 0 0 auto;

4
object-fit може бути хорошим рішенням, якби не пропустити підтримку в IE та Edge навіть до Edge 14
daniels


Я сам використовував цю резервну роботу, працює дуже добре.
Матті Валаам

1
@daniels Edge тепер має в розробці об'єкт: developer.microsoft.com/en-us/microsoft-edge/platform/status/…
AMDG

1
object-fit: contain;зробив фокус для мене, коли у мене були проблеми лише в хромі, ff було добре.
Бенджамін Пітер

53

Не потрібно додавати містити div.

За замовчуванням для властивості css "align-items" є "stretch", що спричиняє розтягнення ваших зображень на повну оригінальну висоту. Встановлення властивості css "align-items" на "flex-start" виправляє вашу проблему.

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}

3
А-а-а ... дякую, що насправді робиш підтримуваний спосіб. Я читав відповіді до цього, і не міг повірити, що все, що ми мали, були брудними хаками ..
Фелікс Ганьон-Греньє,

35

Більшість зображень із внутрішніми розмірами , тобто природного розміру, як jpegзображення. Якщо вказаний розмір визначає одну з ширини та висоти, відсутнє значення визначається за допомогою внутрішнього співвідношення ... - див. MDN .

Але це не працює, як очікувалося, якщо зображення, які встановлюються як прямі гнучкі елементи з поточним модулем гнучкої компоновки, рівень 1 , наскільки я знаю.

Дивіться ці дискусії та звіти про помилки, можливо, пов’язані:

  • Flexbugs №14 - Внутрішній розмір Chrome / Flexbox не виконано правильно.
  • Firefox Bug 972595 - Flex контейнери повинні використовувати "flex-основу" замість "width" для обчислення внутрішньої ширини flex елементів
  • Chromium Issue 249112 - У Flexbox дозволяйте внутрішнім співвідношенням сторін повідомляти обчислення основного розміру.

Як вирішення, ви можете обгорнути кожен <img>із символів a <div>чи a <span>.

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5 Мінімальний розмір гнучких елементів

Щоб забезпечити більш розумний мінімальний розмір за замовчуванням для гнучких елементів , ця специфікація вводить нове значення авто як початкове значення властивостей мінімальної ширини та мінімальної висоти, визначених у CSS 2.1.


Крім того, ви можете використовувати tableмакет CSS , на який ви отримаєте подібні результати, оскільки flexboxвін буде працювати в більшості браузерів, навіть для IE8.

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>


Перший фрагмент потребує .slider > div{min-width:0}нових веб-переглядачів, які підтримують min-width: auto.
Оріол

3
Специфікація flexbox представила нове autoзначення як значення за замовчуванням для min-widthта min-height(раніше воно було 0). Chrome ще не реалізує його, тому ваш перший фрагмент працює. Але нові браузери потребують цього для того, щоб гнучкі елементи зменшувалися менше, ніж ширина зображень за замовчуванням.
Оріол

2
+1 на це слід прийняти відповідь, оскільки мова йде про зображення у моделі флексбоксу, яка є кореневою проблемою в даному випадку ...
Роберт Коритник

Таблиця прекрасна, якщо ваш макет не змінюється на різних точках зламу, але це малоймовірно в наші дні.
шерифдерек

1
А як бути, коли зображення не однакові? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek

6

Я граю навколо флексбоксу останнім часом, і я прийшов до вирішення цього за допомогою експериментів та наступних міркувань. Однак насправді я не впевнений, що саме так і відбувається.

Якщо на реальну ширину впливає система flex. Тож після ширини елементів, що потрапляють на максимальну ширину батьківського, додаткова ширина, встановлена ​​в css, ігнорується. Тоді безпечно встановити ширину на 100%.

Оскільки висота тегу img походить із самого зображення, то встановлення висоти 0% може щось зробити. (саме тут мені незрозуміло, що ... але мені було сенс, що слід це виправити)

DEMO

(пам’ятайте, це бачили тут першими!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

Поки працює лише в хромі


Цікаво, але здається помилка. Відповідно до специфікації , " Відсоток обчислюється відносно висоти сформованого блоку, що містить блок. Якщо висота блоку, що містить, не вказана явно (тобто це залежить від висоти вмісту), і цей елемент не розташований абсолютно , значення обчислюється доauto ". Ось що відбувається на Firefox.
Оріол

jsfiddle.net/xLc2Le0k/8 поясніть різницю у ff та chrome. для цього
Мухаммед Умер

ширина, здається, робить у ff, яка висота роблять у хромі.
Мухаммед Умер

Це цікаво, але я боюся, що рішення лише для X-браузера насправді не є рішеннями. Ваш коментований загадку тут: jsfiddle.net/xLc2Le0k/8 абсолютно захоплюючий , однак, у FF. Здається, це свідчить про те, що FF робить висоту зображення "пропорційною" висоті зображення, якби вона була справді 100%. Іншими словами, img не "знає" про дисплей контейнера: flex. Це пояснює, чому у FF, якщо встановити ширину img на 100%, зображення вище, ніж якщо ви встановите ширину для автоматичного.
coderMe

Це свого роду близько ... але працює тільки в Chrome: jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek

2

Така поведінка очікувана. гнучкий контейнер розтягне всіх своїх дітей за замовчуванням. Зображення не є винятком. (тобто батьків матимеalign-items: stretch майно)

Для збереження співвідношення сторін у нас є два рішення:

  1. Або замініть align-items: stretchвластивість за замовчуванням на align-items: flex-startабо align-self: centerінше, http://jsfiddle.net/e394Lqnt/3/

або

  1. Встановити властивість Align виключно сам дитина: як, align-self: centerабо і align-self: flex-startт.д. http://jsfiddle.net/e394Lqnt/2/

-1

Насправді я з’ясував, що контейнер тегу зображення повинен мати висоту, щоб зберегти співвідношення зображення. наприклад>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

то у ваш HTML ваш контейнер буде загортати зображення тегу

<div class="container"><img src="image.jpg" alt="image" /></div>

ця робота для IE та інших браузерів


-1

У мене просто було те саме питання. Використовуйте гнучку вирівнювання для центрування елементів. Ви повинні використовувати align-items: centerзамість align-content: center. Це дозволить підтримувати співвідношення сторін, тоді як вміст вирівнювання не буде зберігати співвідношення сторін.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.