0

I'm using Bootstrap v4 as the base for this code. Essentially, my problem is this: I'd like to make use of a gradient background for primary buttons, but we make use of outline as well. Because there's not really support for gradient borders, I'm not sure how best to ensure that both buttons end up being the same height & width with that missing 2px border on the primary buttons.

The above screenshot shows the problem. I did come up with this as one fix (which works great in Chrome):

  background-color: var(--background) !important;
  background-image: var(--gradient-background) !important;
  border-width: 2px !important;
  border-style: solid !important;
  border-image-source: var(--gradient-background) !important;
  border-image-slice: 1 !important;

Which (in Chrome) results in this:

enter image description here

which accurately depicts what I want my end result to look like. However, in Firefox, there's a weird bug which ends up like this:

enter image description here

And finally, setting the border to a transparent color adds a weird effect to the edges in both browsers:

enter image description here

Here's a Codepen that's messy but shows correctly the issue with transparent borders: https://codepen.io/anon/pen/ymvYQX

So I'm looking to do any of the following -

1) I would love some help figuring out how to get rid of the bug on Firefox so it renders exactly the same as it does on Chrome.

2) Alternatively, how else can I fix the original issue? Is there another way to force resizing of the buttons? What about a better alternative for the gradient border lines?

Thanks for your help!

IAspireToBeGladOS
  • 1,434
  • 3
  • 19
  • 34
  • My go to solution for "borderless" items that have to be the same size as bordered items is to simply set the border colour to `rgba(0,0,0,0)` – DBS Aug 06 '19 at 16:17
  • Thanks for your input! I edited my original post to show the visual bug that occurs when trying this. – IAspireToBeGladOS Aug 06 '19 at 16:23
  • Would you be able to create a small reproducing example that you can add to your question as a snippet? It helps enormously to be able to see the problem first hand. – DBS Aug 06 '19 at 16:24
  • Sure! Adding it to the question, but here's a codepen that (while messy) demonstrates the issue – IAspireToBeGladOS Aug 06 '19 at 16:31
  • https://codepen.io/anon/pen/ymvYQX – IAspireToBeGladOS Aug 06 '19 at 16:31
  • I added all CSS classes that are being applied to the button (when inspecting the element). – IAspireToBeGladOS Aug 06 '19 at 16:34
  • So, the reason that effect is appearing is as you're seeing the background colour (instead of the background image) behind the transparent border. You could use something like `background-size: 114px; background-position: -2px;` to offset adn grow the background to cover the whole button. I've updated my answer. – DBS Aug 06 '19 at 16:36
  • Thanks so much for explaining that - that makes sense! Fixed. I appreciate your time. – IAspireToBeGladOS Aug 06 '19 at 16:40

3 Answers3

2

You need to increase background-size to cover also the borders, else, you'll see it repeating:

.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle {
    color: #fff;
    background-color: #074c81;
    border-color: #074575;
}
.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active {
    box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-primary:hover {
    color: #fff;
    background-color: #08548d;
    border-color: #074c81;
}
.btn:hover {
    color: #58595b;
    text-decoration: none;
}
button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) {
    cursor: pointer;
}
.Button_root__2FLmr:hover, .Button_root__2FLmr:active, .Button_root__2FLmr:focus {
    outline: none !important;
    box-shadow: none !important;
}
.DrawerGroup_root___Kf5l button {
    margin: 1rem 1rem 0 0 !important;
}
.btn-primary {
    color: #fff;
    background-color: #0a69b1;
    border-color: #0a69b1;
    box-shadow: none;
}
.btn {
    display: inline-block;
    font-weight: 400;
    color: #58595b;
    text-align: center;
    vertical-align: middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    background-color: transparent;
    border: 2px solid transparent;
    padding: 0px 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    border-radius: 9px;
    -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
    transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
button, [type="button"], [type="reset"], [type="submit"] {
    -webkit-appearance: button;
}
.Button_gradientBackground__2z0L9 {
    background-color: #279DD9 !important;
    background-image: linear-gradient(-60deg, #279DD9, #1169B2);
    border: 2px solid transparent !important;
    background-position:center;
    background-size: calc(100% + 4px);/* or 101% is also fine */
}
.btn-outline-secondary {
    color: #6c757d;
    border-color: #6c757d;
}
.Button_root__2FLmr {
    padding: 2px 1rem !important;
    min-width: 7rem;
    white-space: nowrap;
}
<div class="DrawerGroup_root___Kf5l">
  <button type="button" class="Button_root__2FLmr Button_gradientBackground__2z0L9 btn btn-primary">save</button>
  <button type="button" class="Button_root__2FLmr btn btn-outline-secondary">cancel</button>

</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
1

The easiest way I know of to get "borderless" items that perfectly line up with your bordered items, is simply to use a transparent border.

border-color: rgba(0,0,0,0);

To handle the background issues, you can offset and grow the background image using a combination of background-size and background-position

E.g.

button {
  background: linear-gradient(-60deg, #279DD9, #1169B2);
  border: 2px solid #000;
  width: 80px;
  background-size: 84px;
  background-position: -2px;
}

#b {
  border-color: rgba(0, 0, 0, 0);
}
<button id="a">Button 1</button>
<button id="b">Button 2</button>
DBS
  • 9,110
  • 4
  • 35
  • 53
1

No need to hard code any value. All you need is to add background-origin: border-box;ref so that your background consider the border area too. By default it's padding-box so it will cover the padding area then will repeat inside border:

.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle {
    color: #fff;
    background-color: #074c81;
    border-color: #074575;
}
.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active {
    box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-primary:hover {
    color: #fff;
    background-color: #08548d;
    border-color: #074c81;
}
.btn:hover {
    color: #58595b;
    text-decoration: none;
}
button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) {
    cursor: pointer;
}
.Button_root__2FLmr:hover, .Button_root__2FLmr:active, .Button_root__2FLmr:focus {
    outline: none !important;
    box-shadow: none !important;
}
.DrawerGroup_root___Kf5l button {
    margin: 1rem 1rem 0 0 !important;
}
.btn-primary {
    color: #fff;
    background-color: #0a69b1;
    border-color: #0a69b1;
    box-shadow: none;
}
.btn {
    display: inline-block;
    font-weight: 400;
    color: #58595b;
    text-align: center;
    vertical-align: middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    background-color: transparent;
    border: 2px solid transparent;
    padding: 0px 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    border-radius: 9px;
    -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
    transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
button, [type="button"], [type="reset"], [type="submit"] {
    -webkit-appearance: button;
}
.Button_gradientBackground__2z0L9 {
    background-color: #279DD9 !important;
    background-image: linear-gradient(-60deg, #279DD9, #1169B2);
    border: 2px solid transparent !important;
    background-position:center;
    background-origin: border-box;
}
.btn-outline-secondary {
    color: #6c757d;
    border-color: #6c757d;
}
.Button_root__2FLmr {
    padding: 2px 1rem !important;
    min-width: 7rem;
    white-space: nowrap;
}
<div class="DrawerGroup_root___Kf5l">
  <button type="button" class="Button_root__2FLmr Button_gradientBackground__2z0L9 btn btn-primary">save</button>
  <button type="button" class="Button_root__2FLmr btn btn-outline-secondary">cancel</button>

</div>

Related question for more detail: Why doesn't this radial-gradient complete the circle?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415