Closed Bug 567089 Opened 14 years ago Closed 6 years ago

Implement -moz-border-gradient (CSS), for shades or glow effect

Categories

(Core :: CSS Parsing and Computation, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: BenB, Unassigned)

Details

Many nice visual designs use some shade, glow effects around objects.

E.g. Mac OS X uses that for focus rings, see attachment 217956 [details] in bug 333509 and the attachments in bug 53927.
Similar for shades (often very subtle).
Web designs use that as well, but they have to use images for that.

It would be nice to be able to do that with CSS rules only. We already have -moz-border-radius, -moz-border-top-colors (which can emulate this, but it's cumbersome), and -moz-linear-gradient. A -moz-border-gradient (which works in combination with -moz-border-radius) would be a nice and logical addition, and very useful for designers.

xref bug 333509, bug 53927, bug 483696
-moz-border-gradient (and -moz-border-top-gradient, -moz-border-right-gradient etc.) would be defined like -moz-linear-gradient, whereby the draw area is only the border, and its size defined by border-width (and in the corners by -moz-border-radius).
Wouldn't just allowing gradients in border-image (like we do for background-image) work?
Component: Layout: View Rendering → Style System (CSS)
QA Contact: layout.view-rendering → style-system
That would be harder to use, esp. if there's no "border-right-image: <gradient>"
> That would be harder to use

Why?

> esp. if there's no "border-right-image

Hmm.  This is where the way border-image got changed to use slices instead of actual separate images kinda sucks.
I can currently say:
#el1 { background: -moz-linear-gradient(rgb(110,160,185) 40%, rgb(27,112,153) 60%); }
What I expect is to be able to say e.g.:
#el2 {
  border-top-width: 3px;
  border-left-width: 3px;
  border-right-width: 5px;
  border-bottom-width: 5px;
  -moz-border-top-color: -moz-linear-gradient(white 60%, lightgrey 40%);
  -moz-border-left-colors: -moz-linear-gradient(white 60%, lightgrey 40%);
  -moz-border-right-colors: -moz-linear-gradient(darkgrey 40%, white 60%);
  -moz-border-bottom-colors: -moz-linear-gradient(darkgrey 40%, white 60%);
}
or
  -moz-border-color: -moz-linear-gradient(white 60%, lightgrey 40%);
or alternatively
  -moz-border-top-gradient: white 60%, lightgrey 40%;
or
  -moz-border-gradient: white 60%, lightgrey 40%;
s/colors/color/, and the above was just a mock for the syntax of course.
SVG images (which dholbert is working on) plus border-image would address this use-case. So we don't necessarily need to add anything here to make the effect work.

If we need it to be more convenient than that, I suggest adding support for some kind of -moz-rectangular-gradient, and supporting that in border-image.
Given that there's only one border-image, I guess it will be cumbersome to use, I have to slice it, and get top/left and right/bottom just right in one gradient.

As I said, you can already do it now with images or with -moz-border-right-colors (plural).

I just want to say "right and top border are gradient from lightgrey to darkgrey", maybe fine-tune it with stops, and that's it, not fiddle around. It's about making it simple and clean, for an often needed use case that designers love.
(In reply to comment #8)
> As I said, you can already do it now with images or with
> -moz-border-right-colors (plural).

Neither of those will give you correct rendering as you zoom in.

> I just want to say "right and top border are gradient from lightgrey to
> darkgrey", maybe fine-tune it with stops, and that's it, not fiddle around.
> It's about making it simple and clean, for an often needed use case that
> designers love.

With rectangular gradients, it could be as simple as

border-width: 4px 4px 0 0;
border-image: rectangular-gradient(lightgrey, darkgrey 4px)

assuming we specify that for rectangular-gradient, the stop at 0 is the edge of the rectangle and the stop at 100% is the central line segment of the rectangle.
(In reply to comment #9)
> With rectangular gradients, it could be as simple as
> 
> border-width: 4px 4px 0 0;
> border-image: rectangular-gradient(lightgrey, darkgrey 4px)
> 
> assuming we specify that for rectangular-gradient, the stop at 0 is the edge of
> the rectangle and the stop at 100% is the central line segment of the
> rectangle.

Don't you mean the outer and inner edges of the border area (not the border rectangle)?  If the 100% stop is the central line segment of the rectangle, then the color of the innermost stripe of the visible gradient will depend on the size of the rectangle, which is probably not what anyone wants.

Also, can we manage to use border-*-color for this instead of border-image?  If we use border-image, then we have to define what all its extra knobs do when the <image> is a gradient.
(In reply to comment #10)
> Don't you mean the outer and inner edges of the border area (not the border
> rectangle)?  If the 100% stop is the central line segment of the rectangle,
> then the color of the innermost stripe of the visible gradient will depend on
> the size of the rectangle, which is probably not what anyone wants.

No. In my example, I set the darkgrey at 4px. So the gradient starts at lightgrey at the border-box, proceeds to darkgrey at 4px (corresponding to the padding-box in this case), and then remains darkgrey all the way to the center of the rectangle.

> Also, can we manage to use border-*-color for this instead of border-image?  If
> we use border-image, then we have to define what all its extra knobs do when
> the <image> is a gradient.

Why? The gradient generates a rectangular image just like any other image.
(In reply to comment #11)
> (In reply to comment #10)
> > Don't you mean the outer and inner edges of the border area (not the border
> > rectangle)?  If the 100% stop is the central line segment of the rectangle,
> > then the color of the innermost stripe of the visible gradient will depend on
> > the size of the rectangle, which is probably not what anyone wants.
> 
> No. In my example, I set the darkgrey at 4px. So the gradient starts at
> lightgrey at the border-box, proceeds to darkgrey at 4px (corresponding to the
> padding-box in this case), and then remains darkgrey all the way to the center
> of the rectangle.

Oh, I see, that's what the extra 4px is doing.  Still, I'd rather have a definition where you could just write

  border-color: -moz-rectangular-gradient(lightgrey, darkgrey)

and be done.

> > If we use border-image, then we have to define what all its extra
> > knobs do when the <image> is a gradient.
> 
> Why? The gradient generates a rectangular image just like any other image.

So with border-image and no special treatment for gradients, to get the behavior the OP wanted, I think you have to write this:

  border-width: 4px 4px 0 0;
  border-image: -moz-rectangular-gradient(lightgrey, darkgrey 4px, 
                                          transparent 4px)
        4px 4px 4px 4px / 4px 4px 0 0;

which is repetitive and nonobvious.  The thing you had, well, it's a parse error, but ignoring that, it is going to paint opaque dark grey over the content area's background and possibly put a border on all four sides, contra what was wanted.  (That's why you need the extra color stop.)
You don't need the "transparent 4px" since we didn't specify 'fill' in the border-image.

True, if you want borders to only show up on a couple of sides it's slightly clunky. But if you want the gradient on all sides, which I think is much more common, that's very easy.
... whereas introducing gradients as color values is going add lot of complexity. So is adding a bunch of new border properties. There are too many interacting border properties already.
Anyway, this entire discussion belongs on www-style, not here.
> if you want borders to only show up on a couple of sides it's slightly
> clunky.

Yup, but that's typical for shades and other design effects. It is common.

> ... whereas introducing gradients as color values is going add lot of
> complexity. So is adding a bunch of new border properties. There are too many
> interacting border properties already.

If you just implement the [border property or color value] as a convenience shortcut for border-image, how would that add complexity?
If you think it's easy, write up a spec and propose it on www-style.
(In reply to comment #0)
> Many nice visual designs use some shade, glow effects around objects.

That's what box-shadow exists for.
Two notes:
1. -moz-border-*-colors were removed in bug 1429723.
2. CSS Backgrounds 4 extends border-*-color[1] so it can take a list of colors, which works similar to -moz-border-*-colors.

(In reply to Dão Gottwald [::dao] from comment #18)
> (In reply to comment #0)
> > Many nice visual designs use some shade, glow effects around objects.
> 
> That's what box-shadow exists for.

Correct. And other use cases are covered by border-image and the aforementioned border-*-color extension. So I think there is no need for a separate border gradient property. Do you agree, Ben?

Sebastian

[1] https://drafts.csswg.org/css-backgrounds-4/#the-border-color
Flags: needinfo?(ben.bucksch)
no, box-shadow is only on 2 of 4 sides and therefore doesn't do what's needed here.

Yes, it appears that box-shadow does what I needed to do here.
with outset, length = 0, spread radius = 3, blur radius = 9, shadow color = white
Thanks to box-shadow, and to https://www.cssmatic.com/box-shadow !
Status: NEW → RESOLVED
Closed: 6 years ago
Flags: needinfo?(ben.bucksch)
Resolution: --- → FIXED
> no, box-shadow is only on 2 of 4 sides and therefore doesn't do what's needed here.

Sorry, please strike that phrase. Edit error.
You need to log in before you can comment on or make changes to this bug.