Skip to content

[css-backgrounds] background-clip: border-area #9456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
LeaVerou opened this issue Oct 11, 2023 · 41 comments
Closed

[css-backgrounds] background-clip: border-area #9456

LeaVerou opened this issue Oct 11, 2023 · 41 comments

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Oct 11, 2023

Lots of use cases around specifying a continuous image across the border area, including gradient borders, patterned borders etc.

image image image image image image

From a quick search:

Many of these use cases cannot be done with the 9-slice scaling of border-image, and for others border-image introduces unnecessary restrictions and additional complexity, when essentially all that is needed is to be able to cut the padding-box part of the background out.
Today some of these can be achieved by specifying a border-box background and overlaying a padding-box background with the same color as the backdrop, but that doesn't work in every case. Authors use pseudo-elements to achieve some of these effects.

Why not a syntax to subtract from the area defined by background-clip?

Reading the description above, it's conceivable to ask: If what is needed is the ability to subtract padding-box from border-box, why not just add a syntax to subtract background areas? It could be background-clip syntax (e.g. background clip: border-box - padding-box) or a separate background-subtract: <box># property.

The reason is this introduces 4 * 3 = 12 combinations that need to be implemented and tested, only one of which is actually useful. 6 of which would never even produce an area (e.g. content-box - border-box) and 4 of which (text - *) would almost never produce an area, yet introduce unfathomable implementation complexities.

A single border-area addresses the vast majority of use cases, and keeps implementation complexity in check.

@Afif13
Copy link

Afif13 commented Oct 11, 2023

I will add one of my most active (and searched) Stack Overflow answer around this topic: https://stackoverflow.com/a/51496341/8620333

@Afif13
Copy link

Afif13 commented Oct 11, 2023

One use case would be the classic border-only pie chart where we can rely on conic-gradient() but we need to mask the inside part: https://codepen.io/t_afif/pen/XWaPXZO

Pie Chart CSS only

With the above, the code can be as simple as:

.pie {
  --p: 20; /* the progress*/
  --c: red;
  border: 10px solid #0000;
  border-radius: 50%;
  background: conic-gradient(var(--c) calc(var(--p)*1%),#0000 0) border-area
}

(for the rounded part, two extra radial-gradient will do the job and no need to clip them)

@nt1m
Copy link
Member

nt1m commented Oct 12, 2023

I don't think this is necessarily the ideal solution because once you clip the content inside the element is invisible, only the border remains. So you would need a second element for the actual content. I see this more as a border-image extension. I also wonder if mask-border covers this.

@thebabydino
Copy link

thebabydino commented Oct 12, 2023

One use case would be the classic border-only pie chart where we can rely on conic-gradient() but we need to mask the inside part: https://codepen.io/t_afif/pen/XWaPXZO

(for the rounded part, two extra radial-gradient will do the job and no need to clip them)

Love this use case! Now with animation of custom properties via @property finally coming to Firefox (soonish, I hope!), we could animate both the conic-gradient() and the second radial-gradient() by animating --p.


I don't think this is necessarily the ideal solution because once you clip the content inside the element is invisible, only the border remains. So you would need a second element for the actual content. I see this more as a border-image extension. I also wonder if mask-border covers this.

This property is background-clip, it doesn't clip the content, only the background. The content is unaffected. Are there use cases where extending border-image is more appropriate? Yes, but I think there are also use cases for a border-area value for background-clip.


The main advantage that I see over border-image is in the limitations of border-image. border-image doesn't allow layering multiple gradients with different background-size and/or background-position values in order to create border patterns and it doesn't work together with border-radius.


The first use case that came to my mind was that of gradient ghost buttons. I wrote an article detailing it a couple of years back https://css-tricks.com/css-ing-candy-ghost-buttons/

Chrome screenshot. Shows a four row, five column grid of candy ghost buttons with text and an icon following it. These buttons have an elongated pill-like shape, a transparent background and a continuous sweet pastel gradient for the border and the text and icon inside.

The article dissects multiple methods of achieving this they are either more complicated than what this proposal would allow for or they're less than ideal due to using either non-standard, non-cross-browser methods or due to not achieving the exact result we're after. Or both.

This proposal would allow us to create a gradient sized relative to the border-box (background-origin: border-box), layer it twice and clip one layer to the border-area and one layer to text. Since it's the same gradient for both layers and the two areas we clip it to don't intersect, then the Firefox bug 1481498 can't visually break our result.

border: solid var(--b) transparent;
--g: linear-gradient(90deg, #ffda5f, #f9376b) border-box;
background: 
	var(--g) text, 
	var(--g) border-area;
color: transparent

The 1st method dissected in the article is layering and XORing three fully opaque mask layers. The first layer is restricted to the border-box, the second one to the padding-box and XOR-ing them basically gives us the border-area gradient. Then we XOR this intermediate result with the third fully opaque layer, which is restricted to text. And here is where we come across the first problem, text is a non-standard value for mask-clip and isn't supported cross-browser, so this solution only works in Chrome.

The 2nd method uses an extra pseudo with the first two mask layers from before to create the gradient border and also the same gradient clipped to text on the actual element. This works cross-browser, but has the disadvantage of using up an extra pseudo.

The 3rd method uses border-image. This is pretty simple, however, we cannot use this method to achieve the pill shape of the button as radial-gradient and border-image don't play nice together - play with checking/ unchecking the two properties, they both work separately, but not together. This is something else I'd like to see changing, but more on that a bit further down. We can get a tiny corner rounding --r via clip-path: inset(0 round var(--r)), but this corner rounding needs to be at most as big as the border-width, otherwise things will look weird.

The 4th method uses blending. This is very limited when it comes to the backgrounds we can use behind the ghost buttons. Even worse, we can only make it work in Firefox by using up an extra pseudo for it, as it fails there due to bug 1481498 (mentioned above).

So overall, this is one use case where having a border-area value for background-clip makes a lot of sense.


The second use case that comes to mind is "gradient" borders for images obtained out of the image source.

Let's say we have an image:

<img src='myImage.jpg'>

And let's say that we want a spaced out gradient border that goes with the image itself.

Images surrounded by a gap then by a gradient border whose colors are obtained from the image.

border: solid 1em transparent; /* create the border space */
padding: 1em; /* space between image and border */
background: filter(src(attr(src)), blur(50px)) 50%/ cover border-area

There's so much stuff that is poorly supported/ doesn't work in any browser in the code above, but oh, well...

We could of course do this with border-image too, but if we want rounded corners, we're back at the border-image doesn't work with border-radius problem.

And what we need to do nowadays to get such a result is a bit like scratching with the foot behind the ear https://codepen.io/thebabydino/pen/VwqEapG


A demo with pattern borders + rounded corners + (semi)transparent backgrounds examples (Lea might know those gradients, as they're adaptations of some of those from her 10+ year old CSS 3 Patterns gallery).

This is not achievable with border-image, which only accepts one image, cannot take the multiple gradient layers that were used to create these border patterns.

Screenshot


There are also gradient border situations where this wouldn't work however and that's dashed/ dotted gradient borders. There are various ways we could achieve them, but some are terribly hacky and awful (examples one, two, three), others are limited (using a repeating-conic-gradient in the mask to get a dashed gradient border for around a circular disc or round mask sizing to create the gradient dashes on a rectangular element with no rounded corners - examples one, two).

There's no good, consistent CSS way for getting dashed/ dotted gradient borders on elements that maybe have rounded corners without being circular.

Maybe some extension of border-image as suggested above would be better in such cases? One that can work together with border-radius and only paints the gradient in the dashes/ dots if a dashed/ dotted border was specified. If we want dashes/ dots, that makes it less likely we want the kind of complex patterns we cannot achieve with border-image for the reasons explained above.

@fvsch
Copy link

fvsch commented Oct 12, 2023

Love the idea. Definitely something that I’ve needed before.

I like the “quick win” aspect of this proposal, but worry that by using the background as a border it could create issues.

Possible accessibility concern: in a non-supporting UA, users may end up with text contrast issues when the background intended for the border is not clipped.

section {
  border: solid 10px transparent;
  color: black;
  background: linear-gradient(to bottom, black, gray);
  background-clip: border-area;
}

This can be avoided when authors make use of @supports:

section {
  border: solid 10px transparent;
  color: black;
}

@supports (background-clip: border-area) {
  section {
    background: linear-gradient(to bottom, black, gray);
    background-clip: border-area;
  }
}

But we can expect that many authors will not do that (usually because they were testing in a supporting browser, and didn’t realize this was a need). So a better failure mode would be great.

Another related concern is how High Contrast / Forced Colors modes would handle this. Maybe better if they force the background color or replace it with a backplate, and force the border color too.

@kizu
Copy link
Member

kizu commented Oct 12, 2023

@fvsch Yes, it has the same issue as background-clip: text, which has the very similar accessibility concerns mentioned on the MDN page: https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip#accessibility_concerns (though with text it might be even more pronounced for cases where the background does not load at all, resulting in a transparent text).

I'm not sure if there is a good way to fix this outside of the @supports. Actually, I wish there was a way to require wrapping the property with @supports. Like, the feature won't work unless there is a @supports around it?

This way it would be possible to do bad by wrapping only the background-clip property with it, but I think it could be enough of a reminder for any developer that maybe they would need to think this through a bit more.

@LeaVerou
Copy link
Member Author

@nt1m As @thebabydino mentioned, this does not clip the element at all, it's a background property. No, border-clip does not cover it, because that clips the border, it doesn't provide a way to specify gradients and patterns that are only applied to the border. stroke covers a lot of it, but that its a much more complex feature that has so far seen little implementor interest.

@thebabydino Your post made me wonder if what we actually need is background-clip: border instead of border-area, i.e. something that clips to the actual border shape specified by border-style. This satisfies strictly more use cases, since you can always get the border-area behavior by specifying a solid border. Main downside is that it increases implementation complexity, though I’m not sure by how much (@nt1m @emilio ?)

@fvsch Your code suffers from this issue primarily because it's specifying background-clip separately. If it used the shorthand things just take care of themselves automatically, without @supports:

background: linear-gradient(to bottom, black, gray) border-area;

This reminded me, if we add this we should specify that if it's used in the shorthand as a single value it sets background-origin to border-box, since there's no corresponding background-origin value. This also increases the value-add for using the shorthand (since the vast majority of use cases require background-origin: border-box), making authors more likely to favor it over separate longhands.

@kizu It does not have the same issue as background-clip: text because it does not require making text transparent (only the border).


Also CCing my css-backgrounds-4 co-editors @fantasai @SebastianZ

@dharmi04
Copy link

If you have black theme then you can also use neon effects in background of image. It would look great!!

@seyedi
Copy link
Contributor

seyedi commented Nov 27, 2023

I created a video to show how much we need such a feature in CSS!

The best way to create animated gradient borders in CSS

@LeaVerou
Copy link
Member Author

Ok, given the support expressed in the reactions, and the pervasiveness of the use cases, I'm gonna Agenda+ this.

Issues to decide on:

  1. Do we want something like this?
  2. Should it be a keyword that clips to the border area, or to the border shape? There are use cases for both, and unlike what I originally thought, the use cases satisfied by the former are not a subset of the use cases satisfied by the latter (since we don't have multiple borders). The vast majority of use cases are satisfied by both as they just need a solid border that follows border radius, so if the latter involves signficantly higher eng effort, we should just go for the former (nothing precludes adding the latter later).

@SebastianZ
Copy link
Contributor

@LeaVerou Sorry for not answering earlier!

Allowing to clip the background image to the border area is one approach. Though personally, I find it a little hacky to reuse background images for that. I'd rather like to be able to turn off slicing to achieve this, so something like border-image-slice: none;.
We then still have to make borders respect border-radius and allow to define multiple border images, though that feels cleaner to me.

Also note #9183 as a tangential issue.

Sebastian

@fantasai
Copy link
Collaborator

@SebastianZ Aside from the name matching more closely, what would be the benefit of going that route? It seems like a lot of complication to add to border-image, is all of that really needed?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-backgrounds] background-clip: border-area, and agreed to the following:

  • RESOLVED: add background-clip: border-area
The full IRC log of that discussion <emilio> lea: There's a bunch of examples in the thread
<emilio> ... happy to find more if the use cases are not obvious to everybody
<emilio> ... use case is image border but without the border-image scaling, they want a continuous border
<emilio> ... looks like a background image that is clipped only for the border-area
<emilio> ... even though it's not conceptually the best way to do it it seems straight-forward
<emilio> ... proposal is background-clip: border-box area
<emilio> ... which clips to border-box - padding-box
<emilio> ... a better decomposition might be allowing other substraction
<fantasai> +1 to adding border-area to background-clip, this seems straightforward and useful
<emilio> ... but since this is the only use case this seems simpler
<emilio> q+
<astearns> ack emilio
<iank_> q+
<dholbert> emilio (IRC): this is kind of a clip, but an outside clip with an inside clip... seems fine.
<dholbert> emilio (IRC): I'm curious if you've found a use-case with a semitransparent background
<dholbert> lea (IRC): I think it can be conceivable to have a semitransparent bg overlaid on another bg
<dholbert> lea (IRC): or even have it on the outside, and clip the bg to padding-box
<lea> q+ just remembered another design decision to make (clip to border-style or not?)
<dholbert> emilio (IRC): I'm looking at an example with oriol. There's a way to do this if you just draw a solid background on the same element
<lea> q+
<dholbert> emilio (IRC): seems fine to do this. thinking about use-cases for translucent elements.
<dholbert> emilio (IRC): Presumably this wouldn't interfere with border-image?
<dholbert> fantasai (IRC): it'd be underneath
<dholbert> emilio (IRC): seems fine I think
<astearns> ack iank_
<emilio> iank_: What happens with scrollable areas?
<emilio> fantasai: same that happens with backgrounds, it's just a background
<emilio> ... it's clipping out the entire padding area
<schenney> q+
<emilio> ... so you're only drawing the background inside the border area
<astearns> ack lea
<emilio> lea: one thing I'm not sure about is clipping border-box - padding-box
<emilio> ... not sure if we have use cases for other boxes
<emilio> ... someone pointed out that you can use a solid background over the padding box
<astearns> ack dbaron
<emilio> ... but that is not quite general because it might not be a solid color
<emilio> dbaron: I just want to clarify that this is clipping to border-area but it's not affected by border-style
<dbaron> dashed/dotted/double
<emilio> lea: yes, we might get use cases for that but this proposal covers most use cases
<astearns> ack schenney
<emilio> schenney: re. scrolling backgrounds, what about background-position: fixed?w
<emilio> s/w//
<emilio> lea: I think fixed is fixed to the viewport, local is what you are pointing out
<emilio> ... it'd move like it does now
<emilio> schenney: in the local area you don't want to clip necessarily to the padding box
<iank_> q+
<astearns> ack fantasai
<emilio> fantasai: you'd use a repeating pattern and you're painting that on the border box and subtracting the padding box
<astearns> ack iank_
<emilio> schenney: not sure what'd happen, and I know Chromium's background code very well
<emilio> iank_: one thing to consider is interaction with table parts
<emilio> ... what does border collapsing mean with this feature, columns
<emilio> fantasai: I think that falls down from the definitions we already have
<astearns> seems like we should have specified how borders work in all these cases
<emilio> ... there's a border-box we paint into and a padding-box we paint into
<emilio> ... might be that we don't paint anything if they are the same
<emilio> iank_: as long as the spec is clear
<emilio> fantasai: if it's unclear it's unclear about everything that already exists
<emilio> iank_: might be worth mentioning in an out about the expected interaction
<emilio> ... so that they explicitly think about this case
<emilio> florian: even better with test-cases
<emilio> iank_: sure, both!
<emilio> nicole: seems weird to think when a border starts with collapsing
<fantasai> If you paint `background: url(red-swatch) border-box, url(blue-swatch) padding-box`, the part that's red is the part we're proposing to clip to
<emilio> fantasai: I implemented something and got ripped out IIRC, I think right now there's no border
<fantasai> s/no border/no border area for internal table elements/
<emilio> astearns: so proposal is to add a border-area background-clip
<emilio> lea: this is nothing new, it uses existing concepts
<fantasai> s/table elements/table elements in collapsed borders mode/
<emilio> schenney: the result would be the result of background-clip: border-box - background-clip: padding-box right?
<emilio> ... that makes the impl very clear
<emilio> lea: there's an example in IRC from fantasai where that explains
<emilio> RESOLVED: add background-clip: border-area
<lea> 🎉

@jsnkuhn
Copy link

jsnkuhn commented Jun 3, 2024

Was poking around with a checkerboard patterned border as a clipped/masked background. Easy enough to get the pattern to line up correctly on the left and top borders but much harder for the right and bottom.

Note that in this case each corner has a transparent square from the pattern. This would be the same if wanting a white square in each corner.

Maybe I'm missing something. Feels like it should be more straight forward than this.

  background-image: repeating-conic-gradient(rgb(255 255 255/.5) 0 25%, #0000 25% 50%);
  background-size: calc(100% * (2/3) / 11) calc(100% * (2/3) / 11);
  background-origin: border-box;

https://codepen.io/jsnkuhn/pen/jORmpNQ?editors=1100

image

@thebabydino
Copy link

Was poking around with a checkerboard patterned border as a clipped/masked background. Easy enough to get the pattern to line up correctly on the left and top borders but much harder for the right and bottom.

Note that in this case each corner has a transparent square from the pattern. This would be the same if wanting a white square in each corner.

Maybe I'm missing something. Feels like it should be more straight forward than this.

There's background-repeat: round - is that what you're looking for?

@jsnkuhn
Copy link

jsnkuhn commented Jun 18, 2024

Unfortunately not. I'm looking to recreate the design labeled as "2" here created with an SVG border-image. background-repeat: round; would give example "1".

https://codepen.io/jsnkuhn/pen/oWYowL

On the right side of element "2", for example, the last repeat of the generated conic-gradient would need to get cut in half. Trying to make this responsive seems like a separate nightmare:

image

@thebabydino
Copy link

thebabydino commented Jun 19, 2024

A solution using round(). This doesn't size the pattern/ border based on the box size, but the other way around.

width: calc(round(50vmin, #{$s}) - #{.5*$s});
aspect-ratio: 1;
border: solid 1.5*$s transparent;
background: 
	repeating-conic-gradient(
			#000 0% 25%, 
			#0000 0% 50%) 0 0/ #{$s $s};
mask: 
	linear-gradient(red 0 0) exclude, 
	linear-gradient(red 0 0) padding-box

https://codepen.io/thebabydino/pen/yLWvKyK?editors=1100

Animated GIF. Shows a box resizing with the viewport in steps such that it can accommodate for the border pattern to repeat an integer number plus .5 times.

@Afif13
Copy link

Afif13 commented Jun 19, 2024

We can also rely on background-origin. By default it's padding-box so we add that "half" as a border and the repetition will do the job.

div {
  --s: 1em;
	
  width: 12em;
  aspect-ratio: 1;
  border: solid transparent;
  border-width: 0 calc(.5*var(--s)) calc(.5*var(--s)) 0;
  padding: calc(1.5*var(--s)) var(--s) var(--s) calc(1.5*var(--s));
  background: 
    repeating-conic-gradient(#000 0% 25%,#0000 0% 50%) 
    0 0/ var(--s) var(--s) space;
  mask: linear-gradient(red 0 0) exclude, linear-gradient(red 0 0) content-box
}

Demo: https://codepen.io/t_afif/pen/OJYQvev

image

@smfr
Copy link
Contributor

smfr commented Aug 6, 2024

@nt1m suggests that we should allow for clipping to both the border-area and the text: background-clip: text border-area. Should we allow that?

@nt1m
Copy link
Member

nt1m commented Aug 6, 2024

@nt1m suggests that we should allow for clipping to both the border-area and the text: background-clip: text border-area. Should we allow that?

I filed #10696 for this.

@jsnkuhn
Copy link

jsnkuhn commented Aug 12, 2024

https://www.dqx.jp/online/

This is an corners: angle 9999px; use case. Relevant here because of the border-style: double; and gradient coloring.

image

@SebastianZ
Copy link
Contributor

Could you please clarify what is the difference between this new proposed value and the border value already added back in 2017?

Oh wow. I knew my memory is crap but surprised nobody else noticed. 🤣 Did I just commit this in the spec because backgrounds-4 is early enough that editors can do that, or did I actually propose it and get group consensus 2 times?? 🤣🤣🤣

It really looks like everybody missed that... So, since it's already specified, I go ahead and close this issue.

Sebastian

@benfrain
Copy link

Could you please clarify what is the difference between this new proposed value and the border value already added back in 2017?

Apologies for not keeping up here — could somebody clarify — does this mean the use cases above are already catered for by using ‘border’ alongside ‘background-clip’ already? Or it should because it is in the spec, but it is not yet implemented? Or something else entirely? 🤣

@yisibl
Copy link
Contributor

yisibl commented Aug 14, 2024

@benfrain NO, the latest specification has been updated to background-clip: border-area , which has been implemented by WebKit, you can try it out in the latest WebKit Build Archives.

@jsnkuhn
Copy link

jsnkuhn commented Aug 30, 2024

played around with the webkit implementation a bit and found I was making a bad assumption that we'd be able to use different background-clip values on different background layers. As in use one image as a background and another as a border with background-clip: border-box, border-area. But background-clip only takes one value and clips through all the layers.

Was able to add a fake "background-color" with a box-shadow: inset 0 0 0 9999px rgb(0 0 0 / .25);. I assume we might be able to use this to make a simple gradient as well with multiple box-shadows. But feels pretty hacky.

https://codepen.io/jsnkuhn/pen/abgawda

image

@Loirooriol
Copy link
Contributor

But background-clip only takes one value

No, it takes a comma-separated list. https://drafts.csswg.org/css-backgrounds-3/#background-clip

@nt1m
Copy link
Member

nt1m commented Aug 30, 2024

Yes, the WebKit implementation should work with a comma separated list.

@smfr
Copy link
Contributor

smfr commented Aug 30, 2024

Here's a demo with background-clip on both border-area and text: https://codepen.io/smfr/pen/xxoaLNg

@yisibl
Copy link
Contributor

yisibl commented Aug 31, 2024

Demo: https://codepen.io/t_afif/pen/OJYQvev

@Afif13 background-repeat: space had compatibility issues in Safari.

image

I've rewritten it with background-clip: border-area and the code is much easier to understand.

https://codepen.io/yisi/pen/gONdebO?editors=0100

border-area is a huge improvement!

@jsnkuhn
Copy link

jsnkuhn commented Sep 1, 2024

Recreated as best as possible an example from above: #9456 (comment) Not going to be perfect without corner-shape: angle; but the general idea is there.

https://codepen.io/jsnkuhn/pen/OJeoapM

image

Am I understanding this right? To get the background-color to show up as expected on an element with a background-image being used as a border-area we need to add an extra background-image with the value of none like this?:

background-image: linear-gradient(), none;
background-clip: border-area, border-box;

@yisibl
Copy link
Contributor

yisibl commented Sep 2, 2024

Am I understanding this right? To get the background-color to show up as expected on an element with a background-image being used as a border-area we need to add an extra background-image with the value of none like this?:

@LeaVerou @smfr It looks like we need a mechanism to preserve bg-color without having to define multiple bg-images.

@yisibl
Copy link
Contributor

yisibl commented Sep 2, 2024

This reminded me, if we add this we should specify that if it's used in the shorthand as a single value it sets background-origin to border-box, since there's no corresponding background-origin value.
#9456 (comment)

@smfr Do you plan to implement this in WebKit?

@LeaVerou
Copy link
Member Author

LeaVerou commented Sep 2, 2024

Am I understanding this right? To get the background-color to show up as expected on an element with a background-image being used as a border-area we need to add an extra background-image with the value of none like this?:

@LeaVerou @smfr It looks like we need a mechanism to preserve bg-color without having to define multiple bg-images.

I don't think the cost-benefit of that is worth it, unless it provides additional value.

Keep in mind that when using the background shorthand the none doesn't even need to be specified:

background: linear-gradient(...) border-area,
            yellow; /* background-clip: border-box is the initial value */

@jsnkuhn
Copy link

jsnkuhn commented Sep 2, 2024

Updated the pen (https://codepen.io/jsnkuhn/pen/OJeoapM) with a second element using the background shorthand for comparison. The only difference from above is the inclusion of the background-origin on the gradient which seems to be needed in most cases:

@supports (background-clip: border-area) {
  .dqx {
      border-color: transparent;
      background-image:
        linear-gradient(to right, var(--border-color-highlight), var(--border-color-primary) 10% 90%, var(--border-color-highlight)), 
        none;
      background-origin: border-box;
      background-clip: border-area, border-box;
    }

  .dqx-shorthand {
      border-color: transparent;
      background:
        linear-gradient(to right, var(--border-color-highlight), var(--border-color-primary) 10% 90%, var(--border-color-highlight)) border-box border-area, 
        #000;
    }
}

@smfr
Copy link
Contributor

smfr commented Sep 2, 2024

This reminded me, if we add this we should specify that if it's used in the shorthand as a single value it sets background-origin to border-box, since there's no corresponding background-origin value.
#9456 (comment)

@smfr Do you plan to implement this in WebKit?

If there's agreement, and a draft spec update, sure.

@jsnkuhn
Copy link

jsnkuhn commented Sep 2, 2024

played around with border-area and different border-style a bit. 2 notable things:

  1. While Safari seems to have rendering issues with border-style: dotted; with a border-radius above 5px or 6px it appears that the rendered border takes the gradient colors just fine. So seems that this isn't a border-area related issue.

  2. groove, ridge, inset and outset just render as solid with border-area. Unless I'm missing something - this seems OK. I'm not really sure what else you would do in these cases and I'm not sure how much use they get these days any way.

https://codepen.io/jsnkuhn/pen/WNqaeOV

image

@jsnkuhn
Copy link

jsnkuhn commented Sep 3, 2024

One of those fancy border animations with a custom property registered as an <angle>.

https://codepen.io/jsnkuhn/pen/LYKXGPo

Everything seems to be working as intended.

@jsnkuhn
Copy link

jsnkuhn commented Sep 12, 2024

Just as a last thought, I've been playing around with multiple background image layers for each background-clip and haven't run into any rendering issues.

It's probably worth pointing out to developers in public documentation that when we use separate background, border and text properties the browser takes care of the layer order, but when hacking background-image layers to create borders and text like this devs need to make sure we place the images in the correct order ourselves.

It's also worth pointing out that even though these backgrounds might now look like borders or text they are still in fact backgrounds on the background layer. For example background-clipped text will not take text-shadow the way you might expect it to. The text-shadow applies to the transparent text on the text layer and will appear above the clipped background layer text.

Please correct me if I'm wrong but this all seems to come down to the fact that these are provided as temporary hacky solutions to problems while we wait for more complicated official properties like image-fill from the stroke-fill module and what ever ultimately replaces border-image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Wednesday morning
Development

No branches or pull requests