Проблема с использованием единиц vw при появлении вертикальной полосы прокрутки (элементы полной ширины в WordPress)

Я работаю над темой WordPress и хочу, чтобы пользователи могли использовать в ней блоки полной ширины. Для этого я использую следующую структуру HTML/CSS (сведенную к основной проблеме).

(примечание: хотя это для темы WordPress, сама проблема не связана с WordPress, а только с проблемой CSS, так как я даже могу воспроизвести ее с этой очень простой структурой в фрагменте SO)

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
}

.content {
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  overflow-y: visible;
  background: #eee;
}

.alignfull {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  background: #ccc;
}
<div class="content">
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,
    dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <p class="alignfull">
    Some more text - should be full width. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam
    lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. </p>
  <p>Some regular text again. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem
    ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. </p>
</div>

Итак, есть контейнер .content со значением max-width пикселя, центрированный по горизонтали с помощью margin: 0 auto;. Там обычные блоки (то есть первый и последний p здесь) будут иметь значение по умолчанию width: auto, поэтому они будут такой же ширины, как и их родительский блок .content.

Для создания полноразмерного контейнера применяется класс .alignfull (второй p в моем примере). Левое и правое поля для этого определяются как calc(50% - 50vw);, что (когда окно просмотра шире, чем минимальная ширина .content) должно создавать отрицательное значение поля, которое точно соответствует расстоянию между контейнером контента и край области просмотра. Таким образом, этот элемент должен иметь точную ширину области просмотра.

Но это не работает: элемент .alignfull оказывается шире области просмотра на несколько пикселей.

Что я понял:

Это связано с вертикальной полосой прокрутки: если весь контент меньше высоты окна просмотра (т. е. если вертикальная полоса прокрутки не видна), проблема не возникает. Итак, когда присутствует полоса прокрутки, 100% ширина элемента полной ширины меньше 100vw.

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

Есть ли способ заставить его работать правильно, используя значение px для ширины/максимальной ширины контейнера содержимого, как это сделал я?


Дополнение после первого ответа

Должен добавить, что я уже использовал другой метод, которым я тоже не доволен. Это определяет max-width для всех прямых дочерних элементов контейнера контента и изменяет это значение на 100% для .alignfull.

Однако это приводит к некоторым другим проблемам: плавающие элементы не остаются внутри области содержимого, а перемещаются далеко влево или вправо, а элементы, которые по умолчанию имеют левое/правое поля (например, blockquote), теряют свои настройки полей, которые перезаписываются. более конкретным селектором .content>* margin: 0 auto, который необходим для центрирования. (см. пример ниже).

Я знаю, что редактор блоков WordPress помещает плавающие изображения в неплавающий блок (который затем получает максимальную ширину и центрируется), но я хотел бы иметь возможность использовать тот же CSS также для форматов сообщений, для которых редактор блоков деактивирован (используя Disable Gutenberg), и поэтому изображения не обязательно завернуты в неплавающие блоки, т. е. где плавающие изображения (которые не находятся ни в одном контейнере) будут оказаться далеко справа/слева.

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
}

.content>* {
  max-width: 400px;
  margin: 0 auto;
  background: #eee;
}

blockquote {
  margin: 30px 40px;
  background: #fc7;
  color: red;
}

.floated_img {
  float: right;
  width: 20%;
  height: auto;
}

.alignfull {
  max-width: none;
  background: #ccc;
}
<div class="content">
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <img class="floated_img" src="http://lorempixel.com/output/food-h-c-117-198-7.jpg">
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <p class="alignfull">
    Some more text - should be full width. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam
    lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. </p>
  <blockquote>This should be a blockquote</blockquote>
  <p>Some regular text again. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem
    ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. </p>
</div>


person Johannes    schedule 04.11.2019    source источник
comment
Я комментирую, чтобы я мог вернуться к этому вопросу. С Gutenberg я полагался на полное удаление центрирующего контейнера и использование CSS для нацеливания на такие элементы, как p, ul и т. д., которые являются прямыми потомками основного родителя. Я хотел бы лучшего подхода. Отличный вопрос!   -  person disinfor    schedule 04.11.2019
comment
overflow-y: hidden; чтобы скрыть полосу прокрутки? Вместо vh можно попробовать единицу rem (root em), а также vmin и vmax, которые могут помочь.   -  person Jay    schedule 04.11.2019
comment
@Jay Это не только скроет полосу прокрутки, но и обрежет / скроет любой более длинный контент ...   -  person Johannes    schedule 04.11.2019
comment
Я предполагаю, что нет простого и универсального решения, но поскольку мы никогда не хотим, чтобы контент касался краев, я бы приблизил его к этому, просто уменьшив значения: jsfiddle.net/tuw8h46L   -  person Temani Afif    schedule 04.11.2019
comment
@TemaniAfif Ну, полноразмерные изображения определенно должны касаться краев...   -  person Johannes    schedule 04.11.2019


Ответы (1)


Вы правы, говоря, что 100vw не учитывает полосы прокрутки, и это соответствует спецификации. Это ширина окна просмотра, и что бы ни происходило внутри этого окна просмотра, ему все равно.

Вы можете посмотреть на это с другой стороны: сделать ширину по умолчанию равной 100% и сместить узкие элементы с боков.

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

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
}

.content {
  width: 100%;
  margin: 0;
  overflow-y: visible;
}

.content > p {
  background-color: #eee;
  margin: 0;
  padding: 1em 0;
}

.content > p:not(.alignfull) {
  width: 400px;
  margin: 0 auto;
}

.content > p.alignfull {
  background: #ccc;
}
<div class="content">
  <p>Some regular text. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante,
    dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.</p>
  <p class="alignfull">
    Some more text - should be full width. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam
    lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. </p>
  <p>Some regular text again. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem
    ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. </p>
</div>

person Dan    schedule 04.11.2019
comment
Обратите внимание на дополнение к моему вопросу. Я пробовал подобные методы раньше, но мне все равно хотелось бы найти способ, где элементы контейнера определяют максимальную ширину. - person Johannes; 04.11.2019