Чому відсоткова націнка / заливка в CSS завжди обчислюється в залежності від ширини?


130

Якщо ви подивитеся на специфікацію моделі CSS box , ви помітите наступне:

Процент [margin] обчислюється відносно ширини блоку, що генерується, що містить. Зауважте, що це справедливо і для 'margin-top' і 'margin-bottom'. Якщо ширина містить блоку залежить від цього елемента, то отриманий макет не визначений у CSS 2.1. (наголос мій)

Це дійсно так. Але чому ? Що на землі кого-небудь змусить задумати так? Легко придумати сценарії, де ви хочете, наприклад, певна річ завжди повинна бути на 25% вниз від верхньої частини сторінки, але важко придумати будь-яку причину, чому ви хочете, щоб вертикальна накладка була відносно горизонтального розміру батьків.

Ось приклад явища, про яке я маю на увазі:

<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
  This div is 200x800.
  <div style="border: 1px solid blue; margin: 10% 0 0 10%;">
    This div has top-margin of 10% and left-margin of 10% with respect to its parent.
  </div>
</div>

http://jsfiddle.net/8JDYD/


3
Моя початкова думка полягає в тому, що це спричинить неоднозначність щодо того, що margin: 25%насправді означає. Це не було б рівним запасом, навіть якщо код передбачає, що він є. Я не маю доказів, щоб це підтвердити, але це здається розумним.
Райан Кінал

4
jsРозділ моїх думок . Висота набагато більш мінлива, ніж ширина, тому вона зробить зрушення поля навколо важко передбачуваними способами щоразу, коли зміна змісту.
RichardTowers

1
@Ryan: Це правда, це не була б рівна межа, але знову ж таки, якщо ви скажете, що height: 10%; width: 10%ви також не отримаєте квадратного елемента.
mqp

4
Відповідно до dev.w3.org/csswg/css3-box/#the-margin-properties, він стверджує, що Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).так йде обома шляхами
Адам Свіней

1
@Ryan Я думаю, що у нас є переможець. Подивіться тут демонстрацію - jsFiddle
RichardTowers

Відповіді:


60

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

Висота елемента визначається зрістом дітей. Якщо елемент має padding-top: 10% (щодо висоти батьків), це вплине на висоту батьків. Оскільки висота дитини залежить від росту батька, а висота батьків залежить від зросту дитини, у нас буде або неточна висота, або нескінченна петля. Звичайно, це впливає лише на той випадок, коли зсув батьків === батьків, але все ж. Це незвичайний випадок, який важко вирішити.

Оновлення: Останні пари пропозицій можуть бути не зовсім точними. Висота елемента листа (дитина без дітей) впливає на висоту всіх елементів над ним, тому це впливає на багато різних ситуацій.


1
Зверніть увагу, що з цього правила є винятки - розділ 10.6 CSS2.1 охоплює майже всі випадки обчислення висоти для різних типів коробок. Дійсно, випадки, що пов’язані із залежністю між батьком та дитиною у зрості, як правило, призводять до невизначеної поведінки.
BoltClock

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

9
Чому W3C постійно робить це? Мабуть, «семантичний» для W3C є еквівалентом необхідності обслуговувати людей, які не можуть мислити логічно, що не має сенсу. Це як скаржитися на те, наскільки заплутані та німі люди у світі, а потім поширюють більше плутанини та глупоти. Викладене вами міркування не має сенсу: той же аргумент стосується і ширини, але це працює чудово. Все, що було б потрібно, це встановити контекст і напрямок, за якими визначаються висоти, якщо тільки висота батьків не встановлена ​​в пікселях або щось незмінне, тоді проблем не так багато.
u353,

3
Ця залежність - це алгебраїчна формула, яка має рішення, і не призведе до нескінченного циклу, якщо ви не вирішите її розв'язати таким чином, що це не поважає. Скажіть, висота батьків - h_p. Верх підкладки 10% зробить зріст дитини h_c = h_ci + 0.1h_p, де h_ciзнаходиться внутрішня висота дитини і не залежить від росту батьків. Для однієї дитини ви просто знаєте батьківський зріст з рівняння h_p = h_ci + 0.1h_p=> h_p = h_ci / 0.9. Ви завжди можете це зробити, незалежно від того, скільки у вас дітей, навіть для різної подушки. Це лише одне невідоме ( h_p) і одне рівняння.
jeteon

2
Я не думаю, що нескінченний розрахунок є причиною. Проста причина полягає в тому, що: використання widthрезультатів тієї ж проблеми по горизонталі.
Радість

30

Щоб "n%" запас (і підкладка) був однаковим для поля "маржина" вгорі / маргіна праворуч / маржа-низ / маржа-ліворуч, усі чотири повинні бути відносно тієї ж основи. Якщо вгорі / внизу використовується інша основа, ніж ліво / праворуч ', то поле "n%" (і накладка) не означатиме однакову реч з усіх чотирьох сторін.

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


... напрочуд проста відповідь. Хоча всі здогадки вище є заслугами, це досить непоганий момент. Мабуть, випадок, коли декілька рішень було б правильним, тому вони просто вибрали найбільш ймовірний, який буде використаний .... можливо?
dudewad

1
Я припускаю, що було б непогано мати додатковий елемент у синтаксисі, щоб ви могли написати скажіть padding: n [type]. Таким чином, ви мали б padding: 5% logical(що пропонує ОП), на відміну padding: 5% widthвід другого параметра, який дефолтом до "ширини" для зворотної сумісності.
jeteon

5
"n% маржа (та прокладка) не означатиме однакове для всіх чотирьох сторін" - Але чому це буде проблемою?
Гербертуш

4

Я голосую за відповідь від @ChuckKollars після гри з цим JSFiddle (на Chrome 46.0.2490.86) і посилаючись на цю публікацію (написана китайською мовою).


Основна причина проти нескінченної гіпотези розрахунку полягає в тому, що: використання widthстикається з тією ж нескінченною проблемою обчислення .

Подивіться на цей JSFiddle , parentдисплей є inline-block, який може визначити поле / накладення на ньому. childМає значення рентабельності 20%. Якщо ми будемо дотримуватися нескінченної розрахункової гіпотези:

  1. Ширина childзалежить відparent
  2. Ширина parentзалежить відchild

Але в результаті Chrome десь зупиняє обчислення, в результаті чого:

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

Якщо ви спробуєте розгорнути панель "результат" горизонтально на JSFiddle, ви виявите, що ширина їх не зміниться. Зауважте, що вміст у програмі childзагортається у два рядки (не скажімо, один рядок), чому? Я думаю, що Chrome десь важко кодує його. Якщо ви відредагуєте childвміст, щоб збільшити його ( JSFiddle ), ви побачите, що поки горизонтально є зайвий простір, Chrome зберігає вміст у двох рядках.

Тож ми можемо побачити: є певний спосіб запобігти нескінченному обчисленню .


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

Цей пост (написаний китайською мовою) також пропонує ще одну причину: це через орієнтацію читання / набір тексту. Ми читаємо зверху вниз, з фіксованою шириною і нескінченною висотою (практично).


Це тому, що веб-сторінки прокручуються вертикально в загально нескінченному напрямку; тому ширину можна обчислити з ширини вікна браузера. Єдиний спосіб елементів ширший, ніж екран, якщо ви вказали їх ширину бути більшою. Типові елементи блоку шириною 100% і розширюються автоматично у вертикальному напрямку (невідомо). Ось чому ширина не має тієї ж проблеми.
Лусенс Фокс

3

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

Більшість сучасних веб-переглядачів підтримують vw і vh зараз, що дозволяє задавати номери поля на ширину і висоту вікна перегляду.

100vw / 100vh дорівнює 100% ширині / 100% висоті (відповідно), якщо немає смуги прокрутки; якщо є смуга прокрутки, номери вікон перегляду цього не враховують (у той час як% цифр). На щастя, майже всі веб-переглядачі використовують панель прокрутки розміром 17 пікселів ( див. Тут ), тож ви можете використовувати для цього обчислення функції css calc. Якщо ви не знаєте, з’явиться чи ні смуга прокрутки, це рішення не працюватиме.

Наприклад: якщо припустити відсутність горизонтальної смуги прокрутки, верхній запас 50% висоти, можна визначити як "margin-top: 50vh;". За допомогою горизонтальної смуги прокрутки це можна визначити як "margin-top: calc (0,5 * (100vh - 17px))"; (пам’ятайте, що оператори мінус і плюс у calc потребують пробілів з обох сторін!).


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