x
 
Евгений Арутюнов
4 мая 2017
Советы почтой каждую неделю
Пожалуйста, получите наше письмо, чтобы подтвердить свой адрес:
Вы подписаны на «Советы за неделю»:

Пропустите, пожалуйста, без очереди — мне только спросить!

Руст, как элегантно вставить любое ХТМЛ-содержимое в треугольный контейнер?


Если вы можете позволить себе грациозную деградацию для Интернет Эксплорера, то попробуйте clip-path. Если нет, то посмотрите альтернативы в конце совета.

Для примера возьмём два блока как на предложенном примере и добавим туда кнопку для наглядности и проверки кликабельности:

<!-- index.html -->
<div class="background">
  <div class="element">
    <button class="element-button">
      Нажми на меня скорее!
    </button>
  </div>
</div>
/* style.css */
.background {
  box-sizing: border-box;
  background: url(600.png) center / cover;
  width: 300px;
  height: 300px;
  padding: 50px;
}

.element {
  background: url(400.png) center / cover;
  height: 100%;
}

.element-button {
  margin-top: 80%;
  width: 100%;
}
Внутренний квадрат с кнопкой будем обрезать

Свойство clip-path определяет видимую часть элемента с помощью фигуры: многоугольника, круга, эллипса или прямоугольника со скруглёнными углами.

Треугольник можно задать с помощью функции polygon, в которую через запятую передаются координаты точек относительно левого верхнего угла элемента. Зададим три точки так, чтобы получился равнобедренный треугольник как в примере: clip-path: polygon(50% 0, 0% 100%, 100% 100%). Вот, что получилось:

<!-- index.html -->
<div class="background">
  <div class="element">
    <button class="element-button">
      Нажми на меня скорее!
    </button>
  </div>
</div>
/* style.css */
.background {
  box-sizing: border-box;
  background: url(600.png) center / cover;
  width: 300px;
  height: 300px;
  padding: 50px;
}

.element {
  background: url(400.png) center / cover;
  height: 100%;
  clip-path: polygon(50% 0, 0% 100%, 100% 100%);
}

.element-button {
  margin-top: 80%;
  width: 100%;
}
Обрезка с помощью многоугольника. Работает в Хроме и Сафари

Этот пример не заработает в Фаерфоксе, потому что в нём не поддерживается обрезка с помощью фигур.

Но видимую часть элемента можно определить ещё и с помощью ссылки на СВГ-тег <clipPath>, и этот вариант поддерживается в Фаерфоксе:

<!-- index.html -->
<div class="background">
  <div class="element">
    <button class="element-button">
      Нажми на меня скорее!
    </button>
  </div>
</div>

<!-- Создаём СВГ-элемент -->
<svg width="0" height="0">
  <!-- Создаём контейнер clipPath и задаём
  ему идентификатор. Атрибут clipPathUnits
  переключает единицы измерения с абсолютных
  на относительные -->
  <clipPath id="clipTriangle"
    clipPathUnits="objectBoundingBox">
    <!-- Описываем многоугольник с тремя точками.
    Вместо процентов в СВГ используются
    доли от единицы -->
    <polygon points="0.5 0, 0 1, 1 1">
    </polygon>
  </clipPath>
</svg>
/* style.css */
.background {
  box-sizing: border-box;
  background: url(600.png) center / cover;
  width: 300px;
  height: 300px;
  padding: 50px;
}

.element {
  background: url(400.png) center / cover;
  height: 100%;
  /* Ссылаемся на идентификатор СВГ-тега */
  clip-path: url(#clipTriangle);
}

.element-button {
  margin-top: 80%;
  width: 100%;
}
Обрезка с помощью СВГ-элемента. Работает в Хроме, Сафари и Фаерфоксе

Этот способ не такой лаконичный, как хотелось бы, но его можно автоматизировать. Например, postcss-clip-path-polyfill парсит ваш ЦСС и создаёт необходимый для Фаерфокса СВГ-элемент.

В 56 версии Фаерфокса, которая выходит июне, появится полноценная поддержка свойства clip-path.

К сожалению, это свойство совсем не поддерживается в Эдже. И пока не запланировано к реализации.

Но такого эффекта всё-таки можно достичь и в Эдже, встроив разметку элемента прямо в СВГ с помощью тега <foreignObject>

<!-- index.html -->
<div class="background">
  <!-- Создаём СВГ-элемент -->
  <svg class="svg">
    <defs>
      <!-- Как и в предыдущем примере
      описываем обрезающую фигуру -->
      <clipPath id="clipTriangle"
        clipPathUnits="objectBoundingBox">
        <polygon points="0.5 0, 0 1, 1 1">
        </polygon>
      </clipPath>
    </defs>

    <!-- Встраиваем наш элемент с помощью
    тега foreignObject и обрезаем его
    с помощью атрибута clip-path -->
    <foreignObject clip-path="url(#clipTriangle)"
      width="100%" height="100%">
      <div class="element">
        <button class="element-button">
          Нажми на меня скорее!
        </button>
      </div>
    </foreignObject>
  </svg>
</div>
/* style.css */
.background {
  box-sizing: border-box;
  background: url(600.png) center / cover;
  width: 300px;
  height: 300px;
  padding: 50px;
}

.svg {
  position: relative;
  width: 100%;
  height: 100%;
}

.element {
  height: 100%;
  background: url(400.png) center / cover;
}

.element-button {
  margin-top: 80%;
  width: 100%;
}
Обрезка с помощью СВГ-свойств clipPath и foreignObject. Работает в Хроме, Сафари, Фаерфоксе и Эдже

Предполагаю, что это тоже можно автоматизировать, но готовых решений я не встречал.

Альтернативы

Если поддержка Интернет Эксплорера важна или возиться со сборкой СВГ для Эджа не хочется, то можно побробовать схитрить. В следующем совете расскажу, как добиться такого же эффекта другими способами: с помощью ПНГ-маски, хака с трансформациями и ручного позиционирования.

P. S. Мы ищем фронтендера в издательство.

Разработчики Эджа выставляют нереализованные фичи на голосование. Фичи, собравшие больше всего голосов сообщества реализуются в первую очередь. Вы можете проголосовать за внедрение clip-* и mask-* свойств.
P. P. S. Это был совет о веб-разработке. Хотите знать всё о коде, тестах, фронтенд-разработке, цеэсэсе, яваскрипте, рельсах и джейде? Присылайте вопросы.
Вёрстка и прототипирование — дисциплина Школы дизайнеров. Набор закрыт. Оставьте почту, и мы напишем вам, когда откроется следующий набор.
 

Поделиться
Отправить

Комментарии

Александр Зайцев
4 мая 2017

IE 9, Firefox, Opera, Chrome, Safari
https://github.com/codepo8/canvas-masking

Понимаю, что лучше обойтись без JavaScript, но считаю, что по-другому задача сейчас не выполнима.


Цель рубрики — обсуждение вопросов дизайна всех видов, текста в дизайне и взаимоотношений дизайнеров с клиентами.

Мы публикуем комментарии, которые добавляют к уже сказанному новые мысли и хорошие примеры. Мы ожидаем, что такие комментарии составят около 20% от общего числа.

Решение о публикации принимается один раз; мы не имеем возможности комментировать или пересматривать свое решение, хотя оно может быть ошибочно. Уже опубликованные комментарии могут быть удалены через некоторое время, если без них обсуждение не становится менее ценным или интересным.

Вот такой веб 2.0.

EM или REM? 6 Можно ли достичь эффекта переливания без встраивания видео на сайт? 1




Недавно всплыло

Как попросить клиента помочь с дебагом? 1 1 Не знаю, как сказать коллегам о том, что я никудышный сотрудник 2 Пожалуйста, подскажите, как можно написать лучше? Как избавиться от сухости? 1