Создание маски для всех браузеров с использованием CSS-преобразований, сталкивающихся с проблемами позиционирования - PullRequest
3 голосов
/ 03 апреля 2019

Мне нужно создать маску для наложения изображения во всех браузерах на основе vh (нет clip-path)

Я использую div с вращательным преобразованием в качестве маски, а затем на внутреннем, обращая вращение.

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

Я пробовал:

  • позиционирование с верхним и левым значениями без эффекта.
  • Использование transform для перемещения внутреннего контейнера работает, но я не могу найти, как рассчитываются требуемые значения.

https://jsfiddle.net/owfgLnv7/5/

.container {
  width: 70vh;
  height: 100vh;
  background-color: blue;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
}

.tri {
  position: absolute;
  width: 70vh;
  height: 70vh;
  transform: rotate(45deg);
  top: calc((100vh - 70vh) / 2);
  transform-origin: center center;
  background-color: transparent;
  z-index: 2;
  overflow: hidden;
}

.reset-tri {
  position: relative;
  z-index: 1;
  transform: rotate(-45deg);
  transform-origin: center center;
}

.inner-container {
  background: black;
}

Необходимо получить изображение таким образом, чтобы оно было выровнено по левому верхнему краю и проходило нормально

1 Ответ

2 голосов
/ 03 апреля 2019

Обычно, когда элементы преобразованы (повернуты здесь), они выводятся из потока - поэтому измерения не будут вести себя так, как если бы вы этого не делали.

Один из подходов - использование простой математики:

  • если повернуть квадрат на 45 градусов (здесь у вас есть квадрат 70vh) со стороны a, то диагональ будет √2 * a ~ 1.414 * a,
  • , поскольку transform-origin здесь center, это означает, что у вас ширина или высота переполнения равна (1.414 * a - a) / 2 или (1.414 - 1) * a / 2.
  • Аналогичный аргумент может быть указан для ширины container, которая будет иметь ширину, равную width: calc(1.414 * 70vh)

См. Демо ниже:

body {
  margin: 0;
}

.page {
  width: 100vw;
  height: 100vh;
  background: grey;
}

.container {
  width: calc(1.414 * 70vh); /* changed */
  height: 100vh;
  background-color: blue;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
}

.tri {
  position: absolute;
  width: 70vh;
  height: 70vh;
  transform: rotate(45deg);
  top: calc(0.414 * 70vh / 2); /* changed */
  left: calc(0.414 * 70vh / 2); /* added */
  transform-origin: center center;
  background-color: transparent;
  z-index: 2;
  overflow: hidden;
}

.reset-tri {
  position: relative;
  z-index: 1;
  transform: rotate(-45deg);
  transform-origin: center center;
}

.inner-container {
  background: black;
}
<div class="page">
  <div class="container">
    <div class="tri">
      <div class="reset-tri">
        <div class="inner-container">
          <img src="https://openclipart.org/download/230732/360sj3.svg" />
        </div>
      </div>
    </div>
  </div>
</div>

Использование фонового изображения

Для почти идеальной маскировки вы можете:

  • переместите image в background-image в контейнере reset-tri и

  • добавить преобразование scale(1.414) точно в заполнить оригинальный не преобразованный tri контейнер.

См. Демо ниже:

body {
  margin: 0;
}

.page {
  width: 100vw;
  height: 100vh;
  background: grey;
}

.container {
  width: calc(1.414 * 70vh); /* changed */
  height: 100vh;
  background-color: blue;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
}

.tri {
  position: absolute;
  width: 70vh;
  height: 70vh;
  transform: rotate(45deg);
  top: calc(0.414 * 70vh / 2); /* changed */
  left: calc(0.414 * 70vh / 2); /* added */
  transform-origin: center center;
  background-color: transparent;
  z-index: 2;
  overflow: hidden;
}

.reset-tri {
  position: relative;
  z-index: 1;
  transform: rotate(-45deg) scale(1.414); /* scale by √2 */
  transform-origin: center center;
  width: 70vh;
  height: 70vh;
  /* use a bacground image */
  background-size: cover;
  background-image: url("https://openclipart.org/download/230732/360sj3.svg");
}
<div class="page">
  <div class="container">
    <div class="tri">
      <div class="reset-tri"></div>
    </div>
  </div>
</div>

Использование элемента изображения

Для почти идеальной маскировки без использования background-image вы можете вернуться к предыдущей разметке и добавить object-fit: cover к элементу img, который заполняет размеры его оболочки, inner-container - см. демо ниже:

body {
  margin: 0;
}

.page {
  width: 100vw;
  height: 100vh;
  background: grey;
}

.container {
  width: calc(1.414 * 70vh); /* changed */
  height: 100vh;
  background-color: blue;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
}

.tri {
  position: absolute;
  width: 70vh;
  height: 70vh;
  transform: rotate(45deg);
  top: calc(0.414 * 70vh / 2); /* changed */
  left: calc(0.414 * 70vh / 2); /* added */
  transform-origin: center center;
  background-color: transparent;
  z-index: 2;
  overflow: hidden;
}

.reset-tri {
  position: relative;
  z-index: 1;
  transform: rotate(-45deg) scale(1.414); /* scale by √2 */
  transform-origin: center center;
  width: 70vh;
  height: 70vh;
}

.inner-container {
  height: 100%; /* fill the parent wrapper */
}

.inner-container > img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* the image fills the parent container */
}
<div class="page">
  <div class="container">
    <div class="tri">
      <div class="reset-tri">
        <div class="inner-container">
          <img src="https://openclipart.org/download/230732/360sj3.svg" />
        </div>
      </div>
    </div>
  </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...