2

This is driving me nuts. I thought this was a masking issue at first (might still be), but it seems that the original version doesn't even work as a background image in some cases.

The only difference between the two is that the latter ("Imgur") was uploaded to Imgur, and appears to be re-saved.

Original
Original metadata

Imgur
Imgur metadata

.mask {
  background-color: navy;
  -webkit-mask-size: 144px;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: 0 0;
  mask-size: 144px;
  mask-repeat: no-repeat;
  mask-position: 0 0;
}
 #orig .mask {
  -webkit-mask-image: url("https://i.stack.imgur.com/ebAGH.png");
  mask-image: url("https://i.stack.imgur.com/ebAGH.png");
}
 #orig .bg {
  background-image: url("https://i.stack.imgur.com/ebAGH.png");
}
 #imgur .mask {
  -webkit-mask-image: url("https://i.stack.imgur.com/LcBj8.png");
  mask-image: url("https://i.stack.imgur.com/LcBj8.png");
}
 #imgur .bg {
 background-image: url("https://i.stack.imgur.com/LcBj8.png");
}
/* just fluff below */
body {
  background-color: #a0a0a0;
  background-image: linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
p {
  background-color: white;
  padding: 5px;
}
.mask, .bg, img {
  border: 1px solid black;
  display: inline-block;
  width: 144px;
  height: 144px;
}
<div id="orig">
  <p>Orignal</p>
  <div class="mask"></div>
  <div class="bg"></div>
  <img src="https://i.stack.imgur.com/ebAGH.png">
</div>
<div id="imgur">
  <p>Imgur</p>
  <div class="mask"></div>
  <div class="bg"></div>
  <img src="https://i.stack.imgur.com/LcBj8.png">
</div>

Why isn't the top original image working for the background?

Also, if I comment out the masking part, the background works again? I am so lost...

EDIT: it appears in Firefox that the background image does work, but it still doesn't work as a mask.

EDIT 2: I should note that this image is not unique and hasn't been corrupted. It was exported from Photoshop or Illustrator (by our designer) along with several other similar images, all of which have the same problem.

Sarke
  • 2,805
  • 2
  • 18
  • 28

3 Answers3

1

This is because per specs the <image> resource used for mask-image is fetched with cross-origin: anonymous:

<mask-source>s and <clip-source>s have special requirements on fetching resources.

User agents must use the potentially CORS-enabled fetch method defined by the [FETCH] specification for all <mask-source>, <clip-source> and <image> values on the mask-image, mask-border-source and clip-path properties. When fetching, user agents must use “Anonymous” mode, set the referrer source to the stylesheet’s URL and set the origin to the URL of the containing document. If this results in network errors, the effect is as if the value none had been specified.

The sub-domain https://i.stack.imgur.com doesn't pass the proper Access-Control-Allow-Origin: * HTTP header and thus the request is blocked.
On the other hand, https://i.imgur.com/ does send the proper headers, so there we can load the image safely:

https://i.stack.imgur.com/ebAGH.png: <img src="https://i.stack.imgur.com/ebAGH.png" crossorigin="anonymous"><br>
https://i.imgur.com/DrErTaH.png: <img src="https://i.imgur.com/DrErTaH.png" crossorigin="anonymous">

(Note that there is this meta request to change StackOverflow's subdomain behavior).


According to BUG 786507 there wasn't really any identified threat here, but this follows an ongoing best-practice "to fully protect images behind CORS".
So that's how it is.


As for why it doesn't work in your Chrome as background-image sometimes, I'm not entirely sure and can't reproduce on my side, but I'd suspect it's some caching issue where they use the cross-origin: anonymous request instead of the default one. You may want to open an issue at https://crbug.com after you check the "Network" panel of your dev-tools.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • 1
    Well of course it had to be ****ing CORS... Thanks for the info, I wasn't aware those certain image uses had a CORS requirement. Our server and CDN has the same problem as SO and their i.stack.imgur.com. – Sarke Oct 11 '22 at 23:55
  • 1
    @Sarke I must admit I find it also a bit strange they do use cross-origin here. Masking shouldn't expose anything. We can basically do what it does in a , without any CORS issue. And I don't think there is any plan to add read-backs from the Paint API so... Maybe SVG `` was the original reason and they just spread it everywhere, I don't know. – Kaiido Oct 11 '22 at 23:59
  • Apparently canvas `drawImage()` has this issue too: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#what_requests_use_cors – Sarke Oct 12 '22 at 00:04
  • 1
    `drawImage` will "taint" the canvas, this means that one won't be able to read the pixel data back, but it's still able to display the image, and even to be used as a mask. I dug [that bug](https://crbug.com/786507) from History, and it seems there never was any real identified threat, just a "best practice" going forward. – Kaiido Oct 12 '22 at 00:08
0

It probably could probably be the scree resolution of the original being set as 2.834 pixels/mm as that is not web standard, but i've added a work around for you by encapsulating it into a image() css function that reencodes it for display, you won't get the 'masked' part but you can use the mask as a mask.

.mask {
  background-color: navy;
  -webkit-mask-size: 144px;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: 0 0;
  mask-size: 144px;
  mask-repeat: no-repeat;
  mask-position: 0 0;
}
 #orig .mask {
  -webkit-mask-image: image(url("https://i.stack.imgur.com/ebAGH.png"));
  mask-image: image(url("https://i.stack.imgur.com/ebAGH.png"));
  
}
 #orig .bg {
  background-image: url("https://i.stack.imgur.com/ebAGH.png");
}
 #imgur .mask {
  -webkit-mask-image: url("https://i.imgur.com/DrErTaH.png");
  mask-image: url("https://i.imgur.com/DrErTaH.png");*/
}
 #imgur .bg {
 background-image: url("https://i.imgur.com/DrErTaH.png");
}
/* just fluff below */
body {
  background-color: #a0a0a0;
  background-image: linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
p {
  background-color: white;
  padding: 5px;
}
.mask, .bg, img {
  border: 1px solid black;
  display: inline-block;
  width: 144px;
  height: 144px;
}
<div id="orig">
  <p>Orignal</p>
  <div class="mask"></div>
  <div class="bg"></div>
  <img src="https://i.stack.imgur.com/ebAGH.png">
</div>
<div id="imgur">
  <p>Imgur</p>
  <div class="mask"></div>
  <div class="bg"></div>
  <img src="https://i.imgur.com/DrErTaH.png">
</div>
Jae
  • 278
  • 1
  • 6
  • Thanks for the reply, but I don't think the print resolution would affect it. Also doesn't explain why the masking makes the background not work. Interesting trick with the image function though. – Sarke Oct 08 '22 at 13:55
  • And it's really the same print size, just in metric. – Sarke Oct 08 '22 at 13:57
0

Most probably that behavior in Chrome is caused by a (security?) bug, which in turn seems to be caused by an aggressive (weird?) optimization.
The DevTools->Network can give some insights on this, the first is we can observe there that resource for mask-image is fetched with sec-fetch-mode: cors.
The optimization becomes obvious if we change the elements order, so that the background-image start to work in Chrome also, moreover the mask-image is working also, even if in Firefox it doesn't work, for example:

.mask {
  background-color: navy;
  -webkit-mask-size: 144px;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: 0 0;
  mask-size: 144px;
  mask-repeat: no-repeat;
  mask-position: 0 0;
}
 #orig .mask {
  -webkit-mask-image: url("https://i.stack.imgur.com/ebAGH.png");
  mask-image: url("https://i.stack.imgur.com/ebAGH.png");
}
 #orig .bg {
  background-image: url("https://i.stack.imgur.com/ebAGH.png");
}
 #imgur .mask {
  -webkit-mask-image: url("https://i.imgur.com/DrErTaH.png");
  mask-image: url("https://i.imgur.com/DrErTaH.png");
}
 #imgur .bg {
 background-image: url("https://i.imgur.com/DrErTaH.png");
}
/* just fluff below */
body {
  background-color: #a0a0a0;
  background-image: linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
p {
  background-color: white;
  padding: 5px;
}
.mask, .bg, img {
  border: 1px solid black;
  display: inline-block;
  width: 144px;
  height: 144px;
}
<div id="orig">
  <p>Orignal</p>
  <div class="bg"></div>
  <div class="mask"></div>
  <img src="https://i.stack.imgur.com/ebAGH.png">
</div>

In this case, in Chrome DevTools->Network, having checked the Disable cache, we can observe only one network request, with sec-fetch-mode: no-cors, for all background-image, mask-image and img.src, most probably triggered by background-image rule, while there are three requests in Firefox. Thus we may conclude that Chrome keeps an in-memory-cache anyway, but that caching seems to be realized by matching the URL, not Request, as it ignores the Request.mode.
Considering this, the conclusion can be made that it does not work in the original elements order because Chrome is using for background-image the cached result of failed request for mask-image, by matching the cache by the same URL.

n--
  • 3,563
  • 4
  • 9