Применение SVG mask в CSS правилах
Топик с подобным же названием не подходит так как не вариант: Практическое применение SVG mask
Интересует именно применение некой маски к обычному html тегу img и так же не интересует анимация маски и прочее что не относится к телу вопроса
Я хочу применить маску SVG к неизвестному количеству изображений но выходит не понятка, изображений не видно, прилогаю код
img {
display: block;
max-width: 100%;
}
.grid {
width: 480px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
margin: auto;
}
.grid-item img {
mask: url(#mask);
}
<svg viewBox="0 0 155 219" width="155" height="219" style="display: none;">
<defs>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect width="100%" height="100%" fill="#000" />
<circle cx="90" cy="90" r="60" fill="#fff" stroke="red" stroke-width="10"/>
<circle cx="50" cy="50" r="40" fill="#fff" stroke="red" stroke-width="10"/>
</mask>
</defs>
</svg>
<div class="grid">
<div class="grid-item">
<img src="https://images.unsplash.com/photo-1619732802548-bfa614fef77b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
<div class="grid-item">
<img src="https://images.unsplash.com/photo-1619782472846-eba4e6fb2275?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
<div class="grid-item">
<img src="https://images.unsplash.com/photo-1619641046270-29a0b73d7a9f?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
<div class="grid-item">
<img src="https://images.unsplash.com/photo-1619787942043-99ae128ca5c1?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=375&q=80" alt="">
</div>
<div class="grid-item">
<img src="https://images.unsplash.com/photo-1619785938189-264b15dc1694?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
</div>
Что надо сделать что бы заработало mask из css ?
Вот такого поведения я хочу добиться
let svg = document.querySelectorAll(".grid svg");
let svgImage = document.querySelectorAll(".grid svg image");
svg.forEach(function(el) {
el.setAttribute("viewBox", "0 0 155 219");
el.setAttribute("xmlns", "http://www.w3.org/2000/svg");
});
svgImage.forEach(function(el) {
el.setAttribute("x", 0);
el.setAttribute("y", 0);
el.setAttribute("width", "100%");
el.setAttribute("height", "100%");
el.setAttribute("preserveAspectRatio", "none");
el.setAttribute("mask", "url(#mask)");
});
.mask {
position: fixed;
top: 0;
left: 0;
opacity: 0;
}
.grid {
width: 480px;
margin: 30px auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 20px;
}
<svg viewBox="0 0 155 219" xmlns="http://www.w3.org/2000/svg" width="155" height="219" class="mask">
<defs>
<mask id="mask">
<rect width="100%" height="100%" fill="black"></rect>
<circle cx="80" cy="120" r="60" fill="white" stroke="#c00" stroke-width="10" />
<circle cx="50" cy="60" r="40" fill="white" stroke="#c00" stroke-width="10" />
</mask>
</defs>
</svg>
<div class="grid">
<div class="grid-item">
<svg>
<image href="https://images.unsplash.com/photo-1619783534896-ae45ba5c78d8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" />
</svg>
</div>
<div class="grid-item">
<svg>
<image href="https://images.unsplash.com/photo-1619732514485-2f6896f9e34c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" />
</svg>
</div>
<div class="grid-item">
<svg>
<image href="https://images.unsplash.com/photo-1619732802548-bfa614fef77b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" />
</svg>
</div>
<div class="grid-item">
<svg>
<image href="https://images.unsplash.com/photo-1619782472846-eba4e6fb2275?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" />
</svg>
</div>
</div>
Ответы (4 шт):
Я единственное что придумал, это подменить тег img на svg > image, идея была моя а вот с реализацией мне помогли, выглядит это так
let images = document.querySelectorAll(".grid .item img");
images.forEach(function(it) {
it.parentNode.innerHTML = `
<svg viewBox="0 0 155 219" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="mask">
<rect width="100%" height="100%" fill="black"></rect>
<circle cx="80" cy="120" r="60" fill="white" stroke="#c00" stroke-width="10" />
<circle cx="50" cy="60" r="40" fill="white" stroke="#c00" stroke-width="10" />
</mask>
</defs>
<image href=" ${it.src} " width="100%" height="100%" x="0" y="0"
preserveAspectRatio="none" mask="url(#mask)"/>
</svg>
`;
});
.grid {
max-width: 980px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 10px;
margin: 30px auto;
}
<div class="grid">
<div class="item">
<img src="https://images.unsplash.com/photo-1619871172071-47964353b0d5?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=401&q=80" alt="">
</div>
<div class="item">
<img src="https://images.unsplash.com/photo-1616425839183-c60d8f310fec?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
<div class="item">
<img src="https://images.unsplash.com/photo-1619059356114-b744d212faa2?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
</div>
<div class="item">
<img src="https://images.unsplash.com/photo-1611948018782-2a6e9c1d5ce6?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=333&q=80" alt="">
</div>
</div>
Вы можете применить SVG в качестве маски и легко настроить его размер и положение (как вы можете с фоновым изображением). Просто убедитесь, что вы установите правильное значение для viewbox:
.img-container {
width: 300px;
height: 300px;
background-color: lightgreen;
margin: 5px;
}
.clipped-img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
-webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 207 167"><path d="M199.6,18.9c-4.3-8.9-12.5-16.4-22.3-17.8c-11.9-1.7-23.1,5.4-32.2,13.2c-9.1,7.8-17.8,16.8-29.3,20.3c-20.5,6.2-41.7-7.4-63.1-7.5C38.7,27,24.8,33,15.2,43.3c-35.5,38.2-0.1,99.4,40.6,116.2c32.8,13.6,72.1,5.9,100.9-15c27.4-19.9,44.3-54.9,47.4-88.6c0.2-2.7,0.4-5.3,0.5-7.9C204.8,38,203.9,27.8,199.6,18.9z"></path></svg>') center/contain no-repeat;
mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 207 167"><path d="M199.6,18.9c-4.3-8.9-12.5-16.4-22.3-17.8c-11.9-1.7-23.1,5.4-32.2,13.2c-9.1,7.8-17.8,16.8-29.3,20.3c-20.5,6.2-41.7-7.4-63.1-7.5C38.7,27,24.8,33,15.2,43.3c-35.5,38.2-0.1,99.4,40.6,116.2c32.8,13.6,72.1,5.9,100.9-15c27.4-19.9,44.3-54.9,47.4-88.6c0.2-2.7,0.4-5.3,0.5-7.9C204.8,38,203.9,27.8,199.6,18.9z"></path></svg>') center/contain no-repeat;
}
<div class="img-container">
<img class="clipped-img" src="https://picsum.photos/id/1074/800/800.jpg">
</div>
<div class="img-container" style="width:500px;">
<img class="clipped-img" src="https://picsum.photos/id/1074/800/800.jpg">
</div>
<div class="img-container" style="width:150px;">
<img class="clipped-img" src="https://picsum.photos/id/1074/800/800.jpg">
</div>
img {
display: block;
width: 100%;
height: 100%;
mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 450 450"><circle cx="170" cy="140" r="80" stroke="black" stroke-width="20"/> <circle cx="250" cy="280" r="150" stroke="black" stroke-width="20"/></svg>');
-webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 450 450"><circle cx="170" cy="140" r="80"/> <circle cx="250" cy="280" r="150"/></svg>');
--c: radial-gradient(farthest-side, #000 calc(100% - 20px), #0002 calc(100% - 8px) 99%, #0000);
-webkit-mask: var(--c) 100% 100%/80% 80%, var(--c) 20% 20% /40% 40%;
-webkit-mask-repeat: no-repeat;
}
html,
body {
margin: 0;
}
.item {
width: 450px;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
svg {
border: 1px solid red;
}
circle {
fill: #fff;
stroke: red;
stroke-width: 30px;
}
<div class="item">
<img src="https://images.pexels.com/photos/2111143/pexels-photo-2111143.jpeg?cs=srgb&dl=pexels-oratto-oficial-2111143.jpg&fm=jpg" alt="">
</div>
Маскирование — это одна из популярных операций (наряду с отсечением), используемая для скрытия частей элемента, которые под маской частично или полностью будут непрозрачны. Существуют различные способы сделать маскирование, как с помощью CSS, так и SVG. Однако, нужно понимать, что здесь имеются свои различия. Не всегда можно получить ожидаемый результат, как от использования бы SVG, применяя свойства CSS.
Автор вопроса для маскирования использует CSS свойство mask: url(#mask);, значение которого ссылается на SVG-элемент. И получает следующий результат:
Я хочу применить маску SVG к неизвестному количеству изображений но выходит не понятка, изображений не видно
И такой результат ожидаем, потому что CSS свойство mask работает не совсем так, как оно работало бы в SVG, в результате чего объект <rect width="100%" height="100%" fill="#000" /> содержимого SVG-элемента полностью перекрывает изображение, поэтому мы его и не видим.
Для того, чтобы получить результат, близкий к ожидаемому, создадим внешний SVG файл со следующим содержимым:
<?xml version="1.0" ?><svg role="img" viewBox="0 0 155 219" width="155" height="219" xmlns="http://www.w3.org/2000/svg">
<circle cx="90" cy="153" r="60" fill="#fff" stroke="red" stroke-width="10" stroke-opacity="0.5" />
<circle cx="45" cy="45" r="40" fill="#fff" stroke="red" stroke-width="10" stroke-opacity="0.5"/>
</svg>
и будем его использовать в качестве маски. Пример:
img {
width: 155px;
height: 219px;
mask: url(https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/SVG_Mask_Circles.svg/155px-SVG_Mask_Circles.svg.png);
-webkit-mask: url(https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/SVG_Mask_Circles.svg/155px-SVG_Mask_Circles.svg.png);
}
<img src="https://images.unsplash.com/photo-1619732802548-bfa614fef77b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619787942043-99ae128ca5c1?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=375&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619785938189-264b15dc1694?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
Результат немного отличается от ожидаемого, потому что элементы содержимого SVG файла расположены на расстоянии друг от друга.
Если использовать такую маску, которую использует автор вопроса, то получим следующий результат:
img {
width: 155px;
height: 219px;
mask: url(https://upload.wikimedia.org/wikipedia/commons/e/e8/SVG_Mask_100.svg);
-webkit-mask: url(https://upload.wikimedia.org/wikipedia/commons/e/e8/SVG_Mask_100.svg);
}
<img src="https://images.unsplash.com/photo-1619732802548-bfa614fef77b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619787942043-99ae128ca5c1?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=375&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619785938189-264b15dc1694?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
Как мы видим, и здесь результат немного отличается от ожидаемого, потому что элементы содержимого SVG файла накладываются друг на друга, тем самым перекрывая друг друга и изображение, в результате чего часть полупрозрачной границы маленького круга обрезается.
Вывод
В данном случае, чтобы получить такой результат, который нужен автору, а именно фигуру, состоящую из элементов с полупрозрачными границами, которые накладываются друг на друга и верхняя остается видимой, проще (по времени) использовать маскирование с помощью SVG. Однако, если правильно создать SVG файл, используя в качестве элементов не круги (<circle>), а произвольные фигуры, то совсем не сложно будет получить нужный результат.
UPD/ Результат, который ожидает автор вопроса:
img {
width: 155px;
height: 219px;
mask: url(https://upload.wikimedia.org/wikipedia/commons/0/0f/SVG_Mask_Redict.svg);
-webkit-mask: url(https://upload.wikimedia.org/wikipedia/commons/0/0f/SVG_Mask_Redict.svg);
}
<img src="https://images.unsplash.com/photo-1619732802548-bfa614fef77b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619787942043-99ae128ca5c1?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=375&q=80" alt="">
<img src="https://images.unsplash.com/photo-1619785938189-264b15dc1694?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80" alt="">