Вигадливі прикраси зображень: магія одного елемента PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Вигадливі декорації зображень: магія одного елемента

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

Правильно, без додаткової розмітки, без div і псевдоелементів. Лише один тег.

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

Серія Fancy Image Decorations

  • Магія одного елемента — ти тут
  • Маски та розширені ефекти наведення (наступає 21 жовтня )
  • Контури та складні анімації (наступає 28 жовтня )

Почнемо з нашого першого прикладу

Перш ніж копатися в коді, давайте перерахуємо можливості для стилізації an без будь-яких додаткових елементів або псевдоелементів. Ми можемо використовувати border, box-shadow, outlineІ, звичайно, background. Додавання фону до зображення може виглядати дивно, тому що ми не можемо його бачити, оскільки воно буде за зображенням, але хитрість полягає в тому, щоб створити простір навколо використання зображення padding та / або border а потім намалюйте наш фон у цьому просторі.

Я думаю, ви знаєте, що буде далі, оскільки я говорив про це background, так? так, градієнти! Усі прикраси, які ми збираємося зробити, покладаються на велику кількість градієнтів. Якщо у вас є слідував за мною деякий час я думаю, що це, мабуть, для вас зовсім не дивно. 😁

Повернемося до нашого першого прикладу:

img {
  --s: 10px; /* control the size */
  padding: var(--s);
  border: calc(2 * var(--s)) solid #0000;
  outline: 1px solid #000;
  outline-offset: calc(-1 * var(--s));
  background: conic-gradient(from 90deg at 1px 1px, #0000 25%, #000 0);
}

Ми визначаємо padding і прозорий border за допомогою змінної --s щоб створити простір навколо нашого зображення, який дорівнює тричі цій змінній.

Чому ми використовуємо обидва padding та border замість того чи іншого? Ми можемо отримати, використовуючи лише один із них, але мені потрібна ця комбінація для мого градієнта, оскільки за замовчуванням початкове значення background-clip is border-box та background-origin дорівнює padding-box.

Ось покрокова ілюстрація, щоб зрозуміти логіку:

Спочатку ми не маємо меж на зображенні, тому наш градієнт створить два сегменти 1px товщини. (Я використовую 3px у цій конкретній демонстрації, щоб це було легше побачити.) Ми додаємо кольорову рамку, і градієнт усе ще дає нам той самий результат усередині області заповнення (через background-origin), але воно повторюється за кордоном. Якщо ми зробимо колір рамки прозорим, ми можемо використовувати повторення, і ми отримаємо потрібну рамку.

Команда outline у демо має негативне зміщення. Це створює квадратну форму у верхній частині градієнта. Це воно! Ми додали гарну прикрасу до нашого зображення за допомогою одного градієнта та outline. Ми могли використати більше градієнтів! Але я завжди намагаюся зробити свій код максимально простим, і я виявив, що додавання outline так краще.

Ось лише градієнтне рішення, яке я використовую padding щоб визначити простір. Той самий результат, але зі складнішим синтаксисом.

Давайте спробуємо іншу ідею:

Для цього я взяв попередній приклад, видалив outline, і застосував a clip-path щоб вирізати градієнт з кожного боку. The clip-path значення трохи багатослівне та заплутане, але ось ілюстрація, щоб краще зрозуміти його пункти:

Вигадливі декорації зображень: магія одного елемента

Я думаю, ви зрозуміли основну думку. Ми збираємося комбінувати фони, контури, обрізки та деякі маскування, щоб отримати різні види декорацій. Ми також збираємося розглянути кілька класних анімацій при наведенні в якості додаткового бонусу! Те, що ми розглянули досі, є лише невеликим оглядом того, що буде!

Кутова рамка

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

--b: 5px; /* border thickness */
background: conic-gradient(from 90deg at top var(--b) left var(--b), #0000 90deg, darkblue 0) 0 0;
background-size: 50px 50px; 
background-repeat: no-repeat;

Ми будемо малювати градієнт з розміром, рівним 50px 50px і помістіть його у верхній лівий кут (0 0). Для конфігурації градієнта ось покрокова ілюстрація, яка показує, як я досяг цього результату.

Ми схильні думати, що градієнти підходять лише для переходу між двома кольорами. Але насправді ми можемо зробити з ними набагато більше! Вони особливо корисні, коли справа доходить до створення різних фігур. Хитрість полягає в тому, щоб переконатися, що у нас є жорсткі зупинки між кольорами, як у прикладі вище, а не плавні переходи:

#0000 25%, darkblue 0

По суті, це означає: «заповніть градієнт прозорим кольором, поки 25% площі, потім заповніть область, що залишилася darkblue.

Можливо, ви чухаєте голову над 0 значення. Це маленький хак для спрощення синтаксису. Насправді ми повинні використовувати це, щоб зробити жорстку зупинку між кольорами:

#0000 25%, darkblue 25%

Так логічніше! Прозорий колір закінчується на 25% та darkblue починається саме там, де закінчується прозорість, різко зупиняючись. Якщо замінити другий на 0, браузер зробить цю роботу за нас, тому це трохи ефективніший спосіб зробити це.

Десь у специфікація, він говорить:

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

0 завжди менше за будь-яке інше значення, тому браузер завжди перетворюватиме його на найбільше значення, яке стоїть перед ним у декларації. У нашому випадку це число 25%.

Тепер ми застосовуємо ту саму логіку до всіх кутів і закінчуємо таким кодом:

img {
  --b: 5px; /* border thickness */
  --c: #0000 90deg, darkblue 0; /* define the color here */
  padding: 10px;
  background:
    conic-gradient(from 90deg  at top    var(--b) left  var(--b), var(--c)) 0 0,
    conic-gradient(from 180deg at top    var(--b) right var(--b), var(--c)) 100% 0,
    conic-gradient(from 0deg   at bottom var(--b) left  var(--b), var(--c)) 0 100%,
    conic-gradient(from -90deg at bottom var(--b) right var(--b), var(--c)) 100% 100%;
  background-size: 50px 50px; /* adjust border length here */
  background-repeat: no-repeat;
}

Я ввів змінні CSS, щоб уникнути деякої надмірності, оскільки всі градієнти використовують однакову конфігурацію кольорів.

Для ефекту наведення я лише збільшую розмір градієнтів, щоб створити повний кадр:

img:hover {
  background-size: 51% 51%;
}

Так це 51% замість 50% — що створює невеликий нахлест і дозволяє уникнути можливих прогалин.

Давайте спробуємо іншу ідею, використовуючи ту саму техніку:

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

img {
  --b: 8px;  /* border thickness*/
  --s: 60px; /* size of the corner*/
  --g: 14px; /* the gap*/
  --c: #EDC951; 

  padding: calc(var(--b) + var(--g));
  background-image:
    conic-gradient(from  90deg at top    var(--b) left  var(--b), #0000 25%, var(--c) 0),
    conic-gradient(from -90deg at bottom var(--b) right var(--b), #0000 25%, var(--c) 0);
  background-position:
    var(--_p, 0%) var(--_p, 0%),
    calc(100% - var(--_p, 0%)) calc(100% - var(--_p, 0%));
  background-size: var(--s) var(--s);
  background-repeat: no-repeat;
  transition: 
    background-position .3s var(--_i,.3s), 
    background-size .3s calc(.3s - var(--_i, .3s));
}
img:hover {
  background-size: calc(100% - var(--g)) calc(100% - var(--g));
  --_p: calc(var(--g) / 2);
  --_i: 0s;
}

Чому --_i та --_p змінні мають підкреслення в назві? Підкреслення є частиною угоди про найменування, яку я використовую для розгляду «внутрішніх» змінних, які використовуються для оптимізації коду. У них немає нічого особливого, але я хочу зробити різницю між змінними, які ми налаштовуємо для керування кадром (наприклад --b, --cтощо) і ті, які я використовую, щоб зробити код коротшим.

Код може виглядати заплутаним і нелегким для розуміння, але я написав a тричастинний ряд де я детально описую таку техніку. Я настійно рекомендую прочитати принаймні першу статтю, щоб зрозуміти, як я отримав код вище.

Ось ілюстрація, щоб краще зрозуміти різні значення:

Показ того самого зображення двох класичних автомобілів тричі для ілюстрації змінних CSS, які використовуються в коді.
Вигадливі декорації зображень: магія одного елемента

Розкриття кадру

Давайте спробуємо інший тип анімації, де ми показуємо повний кадр при наведенні:

Круто, правда? І якщо ви придивитесь уважніше, то помітите, що лінії зникають у протилежному напрямку, коли виводите мишу, що робить ефект ще більш вигадливим! Я використовував подібний ефект у попередня стаття.

Але цього разу замість того, щоб охопити весь елемент, я охоплю лише невелику частину, визначивши a height щоб отримати щось подібне:

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

img {
  --b: 10px; /* the border thickness*/
  --g: 5px; /* the gap on hover */
  --c: #8A9B0F; 

  padding: calc(var(--g) + var(--b));
  --_g: no-repeat linear-gradient(var(--c) 0 0);
  background: 
    var(--_g) var(--_i, 0%) 0,
    var(--_g) 100% var(--_i, 0%),
    var(--_g) calc(100% - var(--_i, 0%)) 100%,
    var(--_g) 0 calc(100% - var(--_i, 0%));
  background-size: var(--_i, 0%) var(--b),var(--b) var(--_i, 0%);
  transition: .4s, background-position 0s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
}

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

Інший? Ходімо!

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

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

Але чому я зробив ширину градієнта 200%? Ви б подумали 100% було б достатньо, правда?

100% повинно бути достатньо, але я не зможу перемістити градієнт, як хочу, якщо залишити його ширину рівною 100%. Це ще одна маленька примха, пов’язана з тим, як background-position працює. Я висвітлюю це попередня стаття. я також опублікував відповідь у Stack Overflow мати справу з цим. Я знаю, що це багато читання, але воно дійсно варте вашого часу.

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

img {
  --c: #8A9B0F; /* the border color */
  --b: 10px; /* the border thickness*/
  --g: 5px;  /* the gap */

  padding: calc(var(--g) + var(--b));
  --_g: #0000 25%, var(--c) 0;
  background: 
    conic-gradient(from 180deg at top    var(--b) right var(--b), var(--_g))
     var(--_i, 200%) 0 / 200% var(--_i, var(--b))  no-repeat,
    conic-gradient(            at bottom var(--b) left  var(--b), var(--_g))
     0 var(--_i, 200%) / var(--_i, var(--b)) 200%  no-repeat;
  transition: .3s, background-position .3s .3s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
  transition: .3s, background-size .3s .3s;
}

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

Поворот кадру

Цього разу ми не будемо малювати рамку навколо нашого зображення, а скоріше скоригуємо вигляд існуючого.

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

Давайте подивимося, як робиться анімація для верхнього градієнта:

Я просто оновлю позицію повторюваного градієнта. Ще нічого особливого! Зробимо те ж саме для правого боку:

Ви починаєте бачити підступ? Обидва градієнти перетинаються в куті, щоб створити ілюзію, коли пряма лінія змінюється на кутову. Давайте видалимо контур і приховаємо перелив, щоб краще його бачити:

Тепер ми додаємо ще два градієнти, щоб покрити залишилися краї, і готово:

img {
  --g: 4px; /* the gap */
  --b: 12px; /* border thickness*/
  --c: #669706; /* the color */

  padding: calc(var(--g) + var(--b));
  --_c: #0000 0 25%, var(--c) 0 50%;
  --_g1: repeating-linear-gradient(90deg ,var(--_c)) repeat-x;
  --_g2: repeating-linear-gradient(180deg,var(--_c)) repeat-y;
  background:
    var(--_g1) var(--_p, 25%) 0, 
    var(--_g2) 0 var(--_p, 125%),
    var(--_g1) var(--_p, 125%) 100%, 
    var(--_g2) 100% var(--_p, 25%);
  background-size: 200% var(--b), var(--b) 200%;
  transition: .3s;
}
img:hover {
  --_p: 75%;
}

Якщо ми візьмемо цей код і трохи підкоригуємо його, ми можемо отримати ще одну класну анімацію:

Чи можете ви зрозуміти логіку цього прикладу? Це твоє домашнє завдання! Код може виглядати страшно, але він використовує ту ж логіку, що й попередні приклади, які ми розглядали. Спробуйте виокремити кожен градієнт і уявіть, як він анімується.

Підводячи підсумок

Це багато градієнтів в одній статті!

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

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

Я збираюся залишити останню демонстрацію, щоб утримувати вас до наступної статті цієї серії. Цього разу я використовую radial-gradient() щоб створити інший смішний ефект наведення. Я дозволю вам розібрати код, щоб зрозуміти, як він працює. Ставте мені запитання в коментарях, якщо ви застрягли!

Серія Fancy Image Decorations

  • Магія одного елемента — ти тут
  • Маски та розширені ефекти наведення (наступає 21 жовтня )
  • Контури та складні анімації (наступає 28 жовтня )

Часова мітка:

Більше від CSS-хитрощі