Чому у CSS Flexbox чому немає властивостей «виправдовувати елементи» та «виправдовувати-само»?


677

Розглянемо головну вісь і поперечну вісь гнучких контейнерів:

введіть тут опис зображення                                                                                                                                                    Джерело: W3C

Щоб вирівняти гнучкі елементи по головній осі, є одна властивість:

Для вирівнювання гнучких елементів по поперечній осі є три властивості:

На зображенні вище головна вісь горизонтальна, а поперечна вісь - вертикальна. Це типові вказівки flex-контейнера.

Однак ці вказівки можна легко змінити із flex-directionвластивістю.

/* main axis is horizontal, cross axis is vertical */
flex-direction: row;
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;

(Поперечна вісь завжди перпендикулярна до головної осі.)

Моя думка в описі того, як працюють осі, полягає в тому, що в жодному напрямку не здається нічого особливого. Основна вісь, поперечна вісь, вони обидві за рівнем важливості і flex-directionполегшують перемикання вперед і назад.

То чому поперечна вісь отримує два додаткові властивості вирівнювання?

Чому align-contentі align-itemsоб'єднані в одну властивість для головної осі?

Чому головна вісь не отримує justify-selfвластивості?


Сценарії, де ці властивості були б корисні:

  • розміщення гнучких предметів у куті гнучких контейнерів
    #box3 { align-self: flex-end; justify-self: flex-end; }

  • зробити групу гнучких елементів вирівняти праворуч ( justify-content: flex-end), але перший елемент вирівняти ліворуч ( justify-self: flex-start)

    Розглянемо розділ заголовка з групою елементів навігації та логотипом. З justify-selfлоготипом можна вирівняти ліворуч, а елементи навігації залишаються вправо, і вся рівномірне налаштування ("згинається") під різні розміри екрана.

  • в ряд з трьох гнучких елементів прикріпіть середній елемент до центру контейнера ( justify-content: center) і вирівняйте сусідні елементи до країв контейнера ( justify-self: flex-startі justify-self: flex-end).

    Зверніть увагу , що значення space-aroundі space-betweenна justify-contentмайно не буде тримати середній елемент в центрі навколо контейнера , якщо сусідні елементи мають різну ширину.

версія jsFiddle


На момент написання статті, немає жодної згадки justify-selfабо justify-itemsв Flexbox специфікації .

Однак у модулі вирівнювання коробки CSS , який є незавершеною пропозицією W3C встановити загальний набір властивостей вирівнювання для використання у всіх моделях коробки, є таке:

введіть тут опис зображення                                                                                                                                                    Джерело: W3C

Ви помітите, що justify-selfі justify-itemsвас розглядають ... але не для flexbox .


Я закінчу ще раз, повторивши головне питання:

Чому немає властивостей "justify-items" та "justify-self"?


4
Як би ви розраховували justify-selfпрацювати на гнучкий предмет? Припустимо, у вас є елементи a, b, c, d з додатковим простором для розповсюдження навколо них, а контейнер flex має justify-content: space-between, тому вони закінчуються як | abcd |. Що би означало додати, наприклад, justify-self: centerабо "виправдати себе": "flex-end" просто до пункту "b"? Куди б ви очікували, що це піде? (Я бачу деякі демонстрації в одній з відповідей тут, але я не бачу чіткого способу, як це працювало б взагалі.)
dholbert

(По черзі: припустимо, що у нас є justify-content: flex-start, тому предмети переповнені на початку, як | abcd |. Що б ви очікували від цього, якщо ви поставите там justify-self: [anything]пункт "b"?)
dholbert

1
@dholbert, Ви писали: Як би ви розраховували justify-selfпрацювати на флекс-елемент? Я б сказав, не так інакше, ніж autoнадбавки вже працюють на гнучких предметах. У вашому другому прикладі, justify-self: flex-endпункт d перемістить його в крайній край. Це саме по собі було б чудовою особливістю, яку autoможна зробити вже на полях. Я поставив відповідь з демонстрацією.
Майкл Бенджамін

2
Я здебільшого бачу більше випадків використання тут, і випадки використання чудові - але складний біт полягає в тому, як підключити це до фактичного способу, який justify-contentі justify-selfвказано, щоб випадки з конфліктами (як сценарії, про які я запитував) чітко і чітко визначені. Як я зазначив у своїй відповіді тут, йдеться{justify|align}-self про вирівнювання елементів у більшому полі, розміром якого є незалежне від {justify|align}-selfзначення, - а в головній осі немає такого поля, для якого вирівнюватиметься гнучкий елемент.
Дольберт

1
RE "нічим не відрізняється від автоматичного поля" - я насправді запитував про те, як ви уявляєте justify-selfта justify-contentчи взаємодіяли б у випадках, коли вони конфліктують (як сценарії, які я виклав). Автоматичні націнки просто взагалі не взаємодіють justify-content- вони вкрадають увесь пробірний простір, перш ніж justify-contentотримують можливість його використовувати. Отже, автоматичні поля не є дуже хорошим аналогом того, як це буде працювати.
dholbert

Відповіді:


1251

Методи вирівнювання гнучких предметів уздовж основної осі

Як зазначено у запитанні:

Щоб вирівняти гнучкі елементи по головній осі, є одна властивість: justify-content

Щоб вирівняти нежорсткі елементи уздовж поперечної осі є три властивості: align-content, align-itemsіalign-self .

Далі питання задає:

Чому немає justify-itemsі justify-selfвластивості?

Одна відповідь може бути: Тому що вони не потрібні.

Специфікація flexbox передбачає два способи вирівнювання гнучких елементів по головній осі:

  1. justify-contentКлючова властивість, і
  2. auto поля

виправдання-зміст

У justify-contentпоєднується власності згинати елементи уздовж головної осі гнучкого контейнера.

Він застосовується до гнучких контейнерів, але стосується лише гнучких предметів.

Існує п'ять варіантів вирівнювання:

  • flex-start ~ Елементи гнучкості упаковуються до початку рядка.

    введіть тут опис зображення

  • flex-end ~ Елементи гнучкості упаковуються в кінці рядка.

    введіть тут опис зображення

  • center ~ Елементи гнучкості упаковуються до центру лінії.

    введіть тут опис зображення

  • space-between~ Елементи гнучкості розташовані рівномірно, при цьому перший елемент вирівняний до одного краю контейнера, а останній - до протилежного краю. Краї, використані першими та останніми елементами, залежать від режимуflex-direction та режиму запису ( ltrабо rtl).

    введіть тут опис зображення

  • space-around~ Те саме, що, space-betweenокрім проміжків напіврозміру на обох кінцях.

    введіть тут опис зображення


Автополе

З auto полем гнучких елементів можна відцентрувати, відставити або упакувати в підгрупи.

На відміну від того justify-content, який застосовується до гнучких контейнерів, autoполя відрізняються від гнучких елементів.

Вони працюють, витрачаючи весь вільний простір у вказаному напрямку.


Вирівняйте групу гнучких елементів праворуч, але перший елемент ліворуч

Сценарій з питання:

  • зробити групу гнучких елементів вирівняти праворуч ( justify-content: flex-end), але перший елемент вирівняти ліворуч ( justify-self: flex-start)

    Розглянемо розділ заголовка з групою елементів навігації та логотипом. З justify-selfлоготипом можна вирівняти ліворуч, а елементи навігації залишаються вправо, і вся рівномірне налаштування ("згинається") під різні розміри екрана.

введіть тут опис зображення

введіть тут опис зображення


Інші корисні сценарії:

введіть тут опис зображення

введіть тут опис зображення

введіть тут опис зображення


Помістіть гнучкий предмет у кут

Сценарій з питання:

  • розміщення гнучких предметів у кутку .box { align-self: flex-end; justify-self: flex-end; }

введіть тут опис зображення


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

введіть тут опис зображення

margin: autoє альтернативою justify-content: centerіalign-items: center .

Замість цього коду на контейнері flex:

.container {
    justify-content: center;
    align-items: center;
}

Ви можете використовувати це на елементі flex:

.box56 {
    margin: auto;
}

Ця альтернатива корисна при центруванні гнучких елементів, які переповнюють контейнер .


Відцентруйте гнучкий елемент і відцентруйте другий гнучкий елемент між першим і краєм

Гнучка ємність вирівнює гнучкі предмети, розподіляючи вільний простір.

Отже, щоб створити рівний баланс , щоб середній предмет міг бути центрований у контейнері з одним елементом поруч, слід ввести противагу.

У наведених нижче прикладах невидимі елементи третього гнучкості (поля 61 та 68) вводяться для врівноваження "реальних" предметів (вікна 63 та 66).

введіть тут опис зображення

введіть тут опис зображення

Звичайно, цей метод не є нічого великого з точки зору семантики.

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

ПРИМІТКА. Наведені вище приклади спрацьовуватимуть - лише з точки зору справжнього центрування - тоді, коли самі зовнішні елементи мають рівну висоту / ширину. Коли гнучкі елементи різної довжини див. Наступний приклад.


Відцентруйте гнучкий елемент, коли сусідні елементи різняться за розміром

Сценарій з питання:

  • в ряд з трьох гнучких предметів прикріпіть середній елемент до центру контейнера (justify-content: center ) і вирівняйте сусідні елементи до країв контейнера ( justify-self: flex-startі justify-self: flex-end).

    Зверніть увагу , що значення space-aroundі space-betweenна justify-contentмайно не будуть тримати середній елемент центрована по відношенню до контейнера , якщо сусідні елементи мають різну ширину ( див демонстраційних ).

Як зазначалося, якщо всі гнучкі елементи не мають однакової ширини чи висоти (залежно від flex-direction), середній елемент не може бути по-справжньому по центру. Ця проблема є вагомим приводом для justify-selfвластивості (призначена, звичайно, для вирішення завдання).

Ось два способи вирішення цієї проблеми:

Рішення №1: Абсолютне позиціонування

Специфікація flexbox дозволяє абсолютно позиціонувати гнучкі елементи . Це дозволяє ідеально орієнтувати середній предмет незалежно від розміру його побратимів.

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

У наведених нижче прикладах середній елемент зосереджений з абсолютним розміщенням, а зовнішні елементи залишаються потоковими. Але таку ж макет можна досягти і зворотним способом: відцентруйте середній елемент justify-content: centerі абсолютно розташуйте зовнішні елементи.

введіть тут опис зображення

Рішення №2: Вкладені контейнери Flex (немає абсолютного позиціонування)

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}
.box71 > span { margin-right: auto; }
.box73 > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
<div class="container">
  <div class="box box71"><span>71 short</span></div>
  <div class="box box72"><span>72 centered</span></div>
  <div class="box box73"><span>73 loooooooooooooooong</span></div>
</div>

Ось як це працює:

  • Діва верхнього рівня (.container ) - це гнучка ємність.
  • Кожен дочірній div ( .box) тепер є гнучким елементом.
  • Кожен .boxелемент задається flex: 1для того, щоб розподілити простір контейнера порівну.
  • Тепер елементи займають увесь простір в ряду і мають рівну ширину.
  • Зробіть кожен елемент (вкладеним) гнучким контейнером та додайте justify-content: center .
  • Тепер кожен span елемент є центрованим гнучким елементом.
  • Використовуйте гнучкі autoполя для зміщення зовнішніх spans вліво та вправо.

Ви також можете відмовитися justify-contentі використовуватиauto виключно маржі.

Але justify-contentтут можна працювати, оскільки autoпріоритет завжди має пріоритет. З специфікації:

8.1. Вирівнювання з auto маржами

Перед вирівнюванням через justify-contentта align-selfбудь-який позитивний вільний простір розподіляється на автоматичні поля в цьому вимірі.


виправдати-зміст: простір-те саме (концепція)

Повернувшись на justify-contentхвилину, ось ідея ще одного варіанту.

  • space-same~ Гібрид space-betweenі space-around. Елементи гнучкості розташовані рівномірно (на зразок space-between), за винятком того, що на обох кінцях є напіврозмірні проміжки (як space-around), на обох кінцях є повнорозмірні простори.

Це розташування може бути досягнуто з ::beforeі ::afterпсевдо-елементів на гнучкому контейнері.

введіть тут опис зображення

(кредит: @oriol для коду та @crl для мітки)

ОНОВЛЕННЯ: браузери почали впроваджувати space-evenly, що виконує вищесказане. Детальніше дивіться у цій публікації: Рівний простір між елементами гнучкості


PLAYGROUND (включає код для всіх прикладів вище)


1
Відповідь вище чохлів головної осі , justify-contentі autoполів. Для іншого боку монети - по поперечної осі , align-items, align-selfі align-content- див цей пост: stackoverflow.com/q/42613359/3597276
Michael Benjamin

4
@MarkW, ви робите справи на justify-selfмайно ... autoполя корисні, але justify-self: centerбуло б ідеально. Способом вирішення представленої вами проблеми було б створення невидимих ​​повторюваних елементів на протилежній стороні. Дивіться мою відповідь тут: stackoverflow.com/q/38948102/3597276
Michael Benjamin

5
space-sameЗараз ваша концепція - реальна річ. Він називається space-evenly, але на даний момент його підтримує лише Firefox: developer.mozilla.org/en-US/docs/Web/CSS/justify-content
benface

1
@benface, Так, ти маєш рацію. Дякуємо, що вказали на це. Я фактично писав про space-evenlyінші відповіді: stackoverflow.com/q/45134400/3597276
Michael Benjamin

1
Фактично, space-evenly він підтримувався в Chrome 57-60, але лише для макета Grid. Це була помилка, яку виправили, і оскільки Chrome 61 там підтримується і для Flexbox. Крім того , є спосіб емуляції без псевдо-елементів: .item { margin-right: auto } .item:first-child { margin-left: auto }.
Ілля Стрельцин

154

Я знаю, що це не відповідь, але я хотів би внести свій внесок у цю справу для того, що воно варте. Було б чудово, якби вони могли випустити justify-selfдля flexbox, щоб зробити його справді гнучким.

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

Я щиро сподіваюся, W3C це помітить і, принаймні, розгляне це. =)

введіть тут опис зображення

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

введіть тут опис зображення

Простота створення дивовижних макетів нескінченна, погляньте на цей «складний» приклад.

введіть тут опис зображення


12
@ Марк це дивовижно! Дякуємо, що знайшли час для цього. Сподіваюся, ви не заперечуєте, але я подав це тут: discourse.wicg.io/t/flexbox-justify-self-property/1146
Zaqx

1
@Zaqx впевнений, чим більше експозиції, тим краще. Серйозно сподіваюся, що вони знайдуть спосіб здійснити цю реальність, хотіли б, щоб мої руки забруднилися на цьому.
Марк

1
Привіт Марк, @Zaqx, я опублікував відповідь, яка може охоплювати деякі випадки використання, згадані в цій відповіді. Я виявив, що багато чого ще можна зробити на головній осі, не потребуючи justify-selfі justify-items.
Майкл Бенджамін

3
@Michael_B Радий, що ви дізнаєтесь більше про флексбокс і цінуєте, що ви витратили час, щоб відформатувати свої замітки у відповідь. Маржа: авто дійсно круто (хоча ви знайдете браузери, які реалізували версії специфікацій flexbox 2009 та 2012 років, не мають еквівалентної функції, що різко знижує можливість використання його на виробничому сайті). Однак навіть у веб-переглядачах, які підтримують маржу: auto, основний випадок використання елемента, який орієнтований щодо його контейнера, тоді як простір існує, все ще неможливий без властивості виправдання self або подібного.
Zaqx

1
@Zaqx, дякую за відгук. І так, я згоден з вами, autoполя не є повною заміною justify-self. Я обережно висловив свій попередній коментар, кажучи, що autoполя охоплюють деякі випадки використання . Як ви зазначали, він не може центрирувати елемент на місці, коли сусідні елементи мають різні розміри. Однак він надає більше варіантів вирівнювання гнучких елементів. Коли я вперше почав вивчати флексбокс, я подумав, що justify-contentневидимі прокладки - єдиний спосіб.
Майкл Бенджамін

20

Це було задано у списку у стилі www, і Tab Atkins (редактор специфікацій) надав відповідь, пояснюючи чому . Я докладно розповім про це тут.

Для початку спочатку припустимо, що наш гнучкий контейнер однорядний (flex-wrap: nowrap ). У цьому випадку чітко існує різниця вирівнювання між основною віссю та поперечною віссю - на головній осі є декілька елементів, але в поперечній осі лише один елемент. Таким чином, має сенс мати налаштовану за позицією "вирівнювати-само" на пересічній осі (оскільки кожен елемент вирівнюється окремо, самостійно), тоді як це не має сенсу в головній осі (оскільки там елементи вирівнюються колективно).

Для багатолінійного флексокса одна і та ж логіка застосовується до кожної "гнучкої лінії". У заданому рядку елементи вирівнюються окремо по осі хреста (оскільки на осі хреста є лише один елемент на рядку), порівняно з основною віссю.


Ось ще один спосіб її фразування: так, все з *-selfі *-contentвластивості про те , як розподілити додатковий простір навколо речей. Але ключова відмінність полягає в тому, що *-selfверсії стосуються випадків, коли на цій осі є лише одна річ , а *-contentверсії - для тих, коли на цій осі потенційно багато речей . Сценарії "одне - проти багатьох речей" - це різні типи проблем, і тому вони мають різні типи варіантів - наприклад, значення space-around/ space-betweenмає сенс для *-content, але не для *-self.

ТАК: На головній осі флексбоксу є багато речей, які розподіляють простір навколо. Тож *-contentвластивість має сенс там, але не *-selfвласність.

Навпаки, у поперечній осі ми маємо і a, *-selfі *-contentвластивість. Один визначає, як ми будемо розподіляти простір навколо безлічі гнучких ліній ( align-content), тоді як інший ( align-self) визначає, як розподілити простір навколо окремих гнучких предметів по осі поперечини, в межах заданої лінії згинання.

(Я ігнорую *-itemsтут властивості, оскільки вони просто встановлюють значення за замовчуванням *-self.)


1
Я розумію, як justify-selfможе бути проблема на осі з декількома елементами на відміну від одного елемента. Однак я дуже сподіваюся, що вони розглянуть це далі, у ситуації з кількома пунктами, як би justify-selfповодитися, оскільки є деякі ситуації, коли це може бути дуже корисним. Наприклад ( stackoverflow.com/questions/32378953/… ).
Марк

Приємно знайти у цьому списку розсилки. Намагаючись обернути голову навколо цього, оскільки я все ще бачу хороші можливості використання justify-self.
Майкл Бенджамін

Я додав трохи більше роз’яснень, пояснюючи, як *-selfйдеться про випадки, коли у нас є лише одна річ для вирівнювання, тоді *-contentяк про випадки, коли у нас є багато речей для вирівнювання. Це робить це трохи зрозумілішим?
dholbert

Так, це більш зрозуміло. Я ціную пояснення. Але, схоже, все зводиться до простої переваги авторів специфікацій, а не до конкретної потреби, заснованої на логіці. З списку розсилки , посилання : The * -self властивості працюють тільки , якщо дитина один в цій осі. Чому? Здається, в цьому немає потреби. Це довільне рішення. Перевага. Насправді, autoполя, які також є частиною специфікації, дозволяють * вирівняти * з декількома елементами у рядку. Немає чітких причин, через які також не можуть з'явитися властивості ключових слів.
Майкл Бенджамін

1

Я знаю, що це не використовує flexbox, але для простого випадку використання трьох предметів (один зліва, один у центрі, один праворуч), це можна зробити легко, використовуючи display: gridбатьків, grid-area: 1/1/1/1;дітей та justify-selfпозиціонування цих дітей.

<div style="border: 1px solid red; display: grid; width: 100px; height: 25px;">
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: left;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: center;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: right;"></div>
</div>


Дякую за відповідь, але це насправді не вирішує питання. Крім того, є простіший спосіб зробити ваш макет: jsfiddle.net/fga89m2o
Майкл Бенджамін

0

Я просто знайшов власне рішення цієї проблеми, або, принаймні, свою проблему.
Я використовував justify-content: space-aroundзамість justify-content: space-between;.

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

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