Using gradient on div border with rounded corners - css

I have some divs that have rounded corners and colored borders. I want the borders of the div to have the gradient so that it will change when the user hovers overs the div.
I have found all of the sites on how to use the gradient (http://css-tricks.com/css3-gradients/, http://gradients.glrzad.com/, etc.) but I still can't figure out how to get this to work for rounded edge borders.
Will someone please guide me to a site that describes how to do this or even help me with the code?

Here is the SIMPLE solution for that :
Outcome : CSS rounded corners with gradient border
.yourClass {
display: inline-flex;
border: double 6px transparent;
border-radius: 80px;
background-image: linear-gradient(white, white), radial-gradient(circle at top left, #f00, #3020ff);
background-origin: border-box;
background-clip: content-box, border-box;
}

You can nest two elements and let the outer div act as the gradient border then you can work around this problem, example:
<div class="container">
<div class="content">
...
</div>
</div>
And then in your CSS:
/*
unprefixed for conciseness, use a gradient generator por production code
*/
.container {
background: linear-gradient(red, black);
}
.content {
background: white;
padding: 10px;
}
For a working example take a look at https://stackoverflow.com/a/7066176/524555

Using a :before element is the most ideal solution in my opinion, as you then have full control via CSS and the HTML markup stays clean.
.circle {
width: 300px;
height: 200px;
background: white;
border-radius: 100%;
position: relative;
text-align: center;
padding: 20px;
box-sizing: border-box;
}
.circle::before {
border-radius: 100%;
width: 100%;
height:100%;
content: '';
background-image: linear-gradient(to bottom, #3acfd5 0%, #3a4ed5 100%);
padding: 10px;
top: -10px;
left: -10px;
position:absolute;
z-index:-1;
}
You can tweak the padding and the top and left values to adjust the border thickness.
Here is a JSFiddle that shows a practival example: http://jsfiddle.net/wschwarz/e2ckdp2v/

I know this answer was already answered and accepted, but I wanted to post a different approach I used, because this accepted answer wouldn't work if the button was over a background with another gradient, or an image, for example.
My solution works only for horizontal gradients and rounded-cornered (but not circle) buttons. I used both the "border-image" property and pseudo-elements to achieve this effect:
The button would have only the top and bottom "border-image" borders. The left and right borders would be completed with pseudo-elements.
Here's a working example:
HTML:
<div class="background">
<button class="button">
My button!
</button>
</div>
CSS:
*, *:before, *:after {
box-sizing: border-box;
}
.background {
background: linear-gradient(to bottom, #002e4b 0%,#1c4722 100%);
width:500px;
height:500px;
display:flex;
align-items:center;
justify-content:center;
}
.button {
box-sizing:border-box;
display: inline-block;
padding:0.5em 0;
background:none;
border:none;
border-top:2px solid #0498f8;
border-bottom:2px solid #0498f8;
border-image: linear-gradient(to right, #0498f8 0%, #4db848 100%);
border-image-slice: 1;
position: relative;
text-transform: lowercase;
transition:background 0.3s;
color: #fff;
cursor: pointer;
font-size:1em;
&:before,
&:after {
content: '';
display: block;
width: 2em;
height: calc(100% + 4px);
border-radius: 3em 0 0 3em;
border: 2px solid #0498f8;
position: absolute;
border-right: none;
transition:background 0.3s;
left: -2em;
top: -2px;
}
&:after {
border-radius: 0 3em 3em 0;
border: 2px solid #4db848;
position: absolute;
border-left: none;
left:auto;
right: -2em;
top: -2px;
}
&:hover {
background:rgba(0,0,0,0.3);
&:after,
&:before {
background:rgba(0,0,0,0.3);
}
}
}
https://jsfiddle.net/fnbq92sc/2/

border="solid 1px transparent"
background="linear-gradient(Canvas, Canvas) padding-box, linear-gradient(red, blue) border-box"
borderRadius="1rem"
second part for background is the gradient you desire ^

Related

CSS rendering bug on rotated :after pseudo elements

I sure hope I did not miss the according discussion on this:
I define an ":after"-pseudo element to create a triangle on top of a <p> (<div> looks the same) using the following CSS-code:
div {
padding-top: 20px;
}
p {
position: relative;
width: 200px;
height: 100px;
display: block;
background-color: #ccc;
margin: 75px auto 0 auto;
}
p:after {
content: "";
position: absolute;
top: -35px;
width: 50px;
height: 50px;
left: 15%;
background: #ccc;
border: 10px solid #fff;
border-color: #fff #fff #ccc #ccc;
transform: rotate(-45deg);
clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.dark {
background-color: #333;
}
.dark p:after {
border: 10px solid #333;
border-color: #333 #333 #ccc #ccc;
}
<div>
<p></p>
</div>
<div class="dark">
<p></p>
</div>
I noticed a thin outer visible edge (seemingly in the given background-color) in Safari, chromium forked Browsers (Chromium, Vivaldi, Brave, Chrome, Edge) and even worse in Firefox (all on Mac OS X 10.14). I took screenshots in different colors (and magnified by 2) to illustrate the issue. All of this on a non-retina 1080p display.
Can anyone explain this to me?
(The clip-path prevents the edge (which surrounds the whole pseudo-element) from reaching down inside the parenting div.)
The issue seems to be related to angles, Specifically any angle that is not a straight angle.
Related issue
In gradients it happens when there's hard stops from one color to the next, the fix is to avoid hard stops and give the colors room to transition so we don't see the pixels.
div {
height: 300px;
width: 300px;
display: inline-block;
}
[problem] {
background: linear-gradient(30deg, black 50%, orange 50%) no-repeat;
}
[solution] {
background: linear-gradient(30deg, black 49%, orange 50%) no-repeat;
}
<div problem></div>
<div solution></div>
Your issue is similar when you rotate the element to an angle that is not straight the edges are jagged We can't use the same idea from gradients Unfortunately.
*,
*:after,
*:before {
padding: 0;
margin: 0;
box-sizing: border-box;
}
div {
background-color: #333;
height: 300px;
width: 300px;
position: relative;
}
div:after {
content: "";
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
background: #ccc;
transform: rotate(1deg);/* any angle that is not right*/
border: 30px solid #333;
}
<div></div>
Though we can clip it, to prevent the hard stop between the :after's background and the background of the parent because they're different.
*,
*:after,
*:before {
padding: 0;
margin: 0;
box-sizing: border-box;
}
div {
background-color: #333;
height: 300px;
width: 300px;
position: relative;
}
div:after {
content: "";
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
background: #ccc;
background-clip: content-box;
transform: rotate(-45deg);
clip-path: polygon(0 0, 100% 0, 100% 100%);
border: 30px solid #333;
}
<div></div>
Original code:
html, body {
margin: 0;
padding: 0;
}
div {
margin: 0;
padding: 20px;
}
p {
position: relative;
width: 200px;
height: 200px;
display: block;
background-color: #ccc;
margin: 75px auto;
padding: 0;
}
p:after {
content: "";
position: absolute;
top: -35px;
width: 50px;
height: 50px;
left: 15%;
background: #ccc;
background-clip: content-box; /* NEW */
border: 10px solid #fff;
border-color: #fff #fff #ccc #ccc;
transform: rotate(-45deg);
clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.dark {
background-color: #333;
}
.dark p:after {
border: 10px solid #333;
/* border-color: #333 #333 #ccc #ccc; */
}
<div>
<p></p>
</div>
<div class="dark">
<p></p>
</div>
Tested in latest Chrome and FF on Win 8
The issue might pop back up with the background itself, You can see it in the demo below
A bit of jaggedness on the sides of the background, it's subtle but you can see it if you're looking for it
*,
*:after,
*:before {
padding: 0;
margin: 0;
box-sizing: border-box;
}
div {
background-color: #333;
height: 300px;
width: 300px;
position: relative;
}
div:after {
content: "";
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
background: #ccc;
background-clip: content-box;
transform: rotate(1deg);
clip-path: polygon(0 0, 100% 0, 100% 100%);
border: 30px solid #333;
}
<div></div>
We can fix it by having 4 gradients on the edges which transition outward from the color of the current background to the color of whatever is behind which would be tricky to manage dynamically.

Down pointing arrow CSS3

I'm trying to create an object like this using CSS3:
Basically this is a down pointing arrow (the blue part). Tried several services such as http://www.cssarrowplease.com/ but they don't produce quite what's needed.
Any clues how such arrows can be made?
.arrow_box {
position: relative;
background: #88b7d5;
}
.arrow_box:after {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(136, 183, 213, 0);
border-top-color: #88b7d5;
border-width: 30px;
margin-left: -30px;
}
<div class="arrow_box"></div>
Use multiple background and gradient like this:
body {
margin:0;
height:100vh;
background:
linear-gradient(blue,blue) top/100% 50px,
linear-gradient(to bottom left,blue 49%,transparent 50%) 0 50px/50.1% 100px,
linear-gradient(to bottom right,blue 49%,transparent 50%) 100% 50px/50.1% 100px,
#000;
background-repeat:no-repeat;
}
You can also rely on border to make the background less complex:
.box {
height:100vh;
border-top:50px solid blue;
background:
linear-gradient(to bottom left,blue 49%,transparent 50%) top left,
linear-gradient(to bottom right,blue 49%,transparent 50%) top right,
#000;
background-size:50.1% 40%;
background-repeat:no-repeat;
box-sizing:border-box;
}
body {
margin:0;
}
<div class="box">
</div>
You could set the background to one color and implement a triangle that points down, like this:
#triangle-down {
width: 0;
height: 0;
border-left: 55px solid transparent;
border-right: 55px solid transparent;
border-top: 125px solid blue;
background: black;
}
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<p id="triangle-down"></p>
</body>
</html>
Obviously, this is a basic example that you can tweak to meet your particular needs.
For more examples, I suggest visiting this site. I hope this was helpful.
You can consider using pseudo code. The example below will look good on small devices. For larger devices a media query needs to be defined using different settings.
body {
margin: 0;
}
.container {
width: 100%;
background-color: black;
height: 200px;
position:relative;
}
.container:before {
content: "";
width: 0;
height: 0;
border-left: 600px solid transparent;
border-right: 600px solid transparent;
border-top: 160px solid darkblue;
position: absolute;
top: 0;
left: -250px;
}
<div class="container"></div>

How to make a triangle hover effect behind menu option

I'm trying to add a hover effect for a menu -
It should be pretty simple but I haven't found any scss or css work arounds yet... Below is an image that shows specifically what I'm talking about.
A simple linear-gradient will do it:
.container {
background:grey;
padding:10px;
}
.nav {
display: inline-block;
padding: 10px;
color: #fff;
}
.nav:hover {
background: linear-gradient(to bottom right, transparent 50%, red 51%);
}
<div class="container">
<div class="nav">TEXT</div>
<div class="nav">long TEXT</div>
<div class="nav">A</div>
<div class="nav">BBBBBBBBBBB</div>
</div>
You can use clip-path to shape the triangle, although browser support Eh.
button {
background: #112b1bb8;
border: 1px solid black;
padding: 10px 40px;
position: relative;
}
button:hover:before {
content: '';
width: 100%;
height: 100%;
background: grey;
position: absolute;
top: 0;
left: 0;
z-index: -1;
clip-path: polygon(0% 100%, 100% 0%, 100% 100%);
}
<button>Brand</button>
<button>Link Link</button>
<button>O</button>

CSS: How to add slanted edge to right of div with complete browser cross-compatability?

I'm looking to achieve a slanted edge on my div. The problem I'm coming across is the simple code I found to accomplish this is not cross-browser compatible. In fact, it only shows in Chrome.
Can anyone advise on how to do the following so it works in ALL browsers:
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
This effect would achieve:
Here's my entire CSS code:
.my-slanted-div {
position:absolute;
bottom:0;
left:0;
width:100px;
padding:10px 10px;
background-color:#eee;
font-size:20px;
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
}
Can anyone help me out?
You can also skew pseudo-element, like this:
.my-slanted-div {
position:absolute;
bottom:40px;
left:0;
width:80px;
padding:10px 10px;
background-color:red;
font-size:20px;
}
.my-slanted-div:after {
width:50px;
background:red;
position:absolute;
height:100%;
content:' ';
right:-22px;
top:0;
transform: skew(45deg);
}
<div class="my-slanted-div">
TEXT
</div>
p.s. change angle, play with values...to get desired result...
Edit: Demo in context -> https://jsfiddle.net/Lbwj40mg/2/
This should do the trick using borders.
<div id="container">
<p id="text">Hello</p>
<div id="slanted"></div>
</div>
#container {
position: relative;
height: 200px;
width: 200px;
background:url(http://placehold.it/200x200);
}
#text {
position: absolute;
bottom: 15px;
left: 10px;
z-index: 1;
margin: 0;
}
#slanted {
position: absolute;
bottom: 0;
left: 0;
height: 0;
width: 0;
border-left: 75px solid #dedede;
border-right: 50px solid transparent;
border-bottom: 50px solid #dedede;
}
jsfiddle
I've made it work one way with :before and :after pseudos, you simply need to update the widths, heights and line-height to suit the size of tab you want; the rectangle must be the same height as the :before and :after bits for a clean look.
.box {
background: red;
width: 200px;
position: relative;
height: 100px;
line-height: 100px;
text-align: center;
margin-left: 50px;
color: white;
font-size: 21px;
font-family: arial, sans-serif;
}
.box:after {
position: absolute;
right: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
.box:before {
position: absolute;
left: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="box">
Text in the box
</div>
Here's a way with transform: rotate just to add to the list. Quite annoying as you will have to play with pixels for alignment and make some entries into #media rules for different screen sizes. But it should be fairly cross browser friendly (but maybe not opera mini)
body {
background-color: #333;
}
.container {
position: absolute; /* needs a position, relative is fine. abolsute just for this example */
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 200px;
background-color: #ccc;
overflow: hidden; /* required */
}
.salutations {
position: absolute;
bottom: 0;
left: 0;
padding: 0 10px 0 15px;
background-color: #fcfcfc;
height: 50px;
line-height: 50px; /* match height to vertically center text */
font-size: 30px;
}
.salutations::before {
content: '';
position: absolute;
top: 21px; /* play with this for alignment */
right: -36px; /* play with this for alignment */
height: 40px; width: 70px; /* may need to adjust these depending on container size */
background-color: #fcfcfc;
transform: rotate(60deg); /* to adjust angle */
z-index: -1; /* puts the pseudo element ::before below .salutations */
}
<div class="container">
<div class="salutations">Hello</div>
</div>
P.S. May have to adjust a pixel or two, my eyes suck.
Browser Compatability
transform: rotate
pseudo elements (::before)
Fiddle
https://jsfiddle.net/Hastig/wy5bjxg3/
It is most likely it is an SVG scaled to always fit its text which is simple and quick way of doing it; if you must use CSS then you could always:
Set a gradient to the div from color to transparent so that it takes up most of the div and the transition of color is abrupt and not smooth like how a normal gradient looks.
create another div and using borders create a triangle to touch the other main rectangular div such as doing:
.triangle {
width: 0;
height: 0;
border-style: solid;
border-width: 200px 200px 0 0;
border-color: #fff transparent transparent transparent;
}
Using css you can generate an element that takes the shape of a triangle.
Css tricks has a post on that.
By making the .slanted class position itself relative, we can position the generated content on the right side of the slanted div using absolute positioning.
It'll take some fiddling to get the perfect result you want, but here's an example.
.slanted{
background: #007bff;
color: #fff;
position: relative;
display:inline-block;
font-size: 20px;
height: 25px;
padding: 2px 4px;
}
.slanted::after {
content: " ";
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 29px 0 0 20px;
border-color: transparent transparent transparent #007bff;
position: absolute;
top: 0;
right: -20px;
}
<div class="slanted">Hello</div>

Responsive CSS triangle with percents width

The code below will create an arrow right below an <a> element:
JSFiddle
.btn {
position: relative;
display: inline-block;
width: 100px;
height: 50px;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
}
.btn:after {
content: "";
position: absolute;
bottom: -10px;
left: 0;
width: 0;
height: 0;
border-width: 10px 50px 0 50px;
border-style: solid;
border-color: gray transparent transparent transparent;
}
Hello!
The problem is that we have to indicate the link width to get an arrow of a proper size because we cannot indicate the border width in pixels.
How to make a responsive triangle percent based?
You could use a skewed and rotated pseudo element to create a responsive triangle under the link :
DEMO (resize the result window to see how it reacts)
The triangle maintains it's aspect ratio with the padding-bottom property.
If you want the shape to adapt it's size according to it's content, you can remove the width on the .btn class
.btn {
position: relative;
display: inline-block;
height: 50px; width: 50%;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
padding-bottom: 15%;
background-clip: content-box;
overflow: hidden;
}
.btn:after {
content: "";
position: absolute;
top:50px; left: 0;
background-color: inherit;
padding-bottom: 50%;
width: 57.7%;
z-index: -1;
transform-origin: 0 0;
transform: rotate(-30deg) skewX(30deg);
}
/** FOR THE DEMO **/
body {
background: url('http://i.imgur.com/qi5FGET.jpg');
background-size: cover;
}
Hello!
For more info on responsive triangles and how to make them, you can have a look at
Triangles with transform rotate (simple and fancy responsive triangles)
Another solution to this would be to use a CSS clip-path to clip a triangle out of a coloured block. No IE support however, but could be used for internal tools etc.
DEMO
Written with SCSS for ease.
.outer {
background: orange;
width: 25%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 1em;
p {
margin: 0;
text-align: center;
color: #fff;
}
&:after {
content: '';
position: absolute;
top: 100%;
left: 0;
right: 0;
padding-bottom: 10%;
background: orange;
-webkit-clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
}
}
I found solution that works with any width/height. You can use two pseudo-elements with linear-gradient background, like this, (fiddle):
.btn {
position: relative;
display: inline-block;
width: 100px;
height: 50px;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
}
.btn:before {
content: "";
position: absolute;
top: 100%;
right: 0;
width: 50%;
height: 10px;
background: linear-gradient(to right bottom, gray 50%, transparent 50%)
}
.btn:after {
content: "";
position: absolute;
top: 100%;
left: 0;
width: 50%;
height: 10px;
background: linear-gradient(to left bottom, gray 50%, transparent 50%)
}
A modified version of the below code can help you to achieve this
HTML
<div class="triangle-down"></div>
CSS
.triangle-down {
width: 10%;
height: 0;
padding-left:10%;
padding-top: 10%;
overflow: hidden;
}
.triangle-down:after {
content: "";
display: block;
width: 0;
height: 0;
margin-left:-500px;
margin-top:-500px;
border-left: 500px solid transparent;
border-right: 500px solid transparent;
border-top: 500px solid #4679BD;
}
For further reading on responsive triangles: CSS triangles made responsive
(archived link)
I tried the other answers and found them to be either too complex and/or unwieldy to manipulate the shape of the triangle. I decided instead to create a simple triangle shape as an svg.
The triangle height can be set to an absolute value, or as a percentage of the rectangle so it can be responsive in both directions if necessary.
html, body{
height:100%;
width:100%;
}
.outer{
width:20%;
height:25%;
background:red;
position:relative;
}
.inner{
height:100%;
width:100%;
background-color:red;
}
.triangle-down{
height:25%;
width:100%;
position:relative;
}
.triangle-down svg{
height:100%;
width:100%;
position:absolute;
top:0;
}
svg .triangle-path{
fill:red;
}
<div class="outer">
<div class="inner"></div>
<div class="triangle-down">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 2 1">
<g>
<path class="triangle-path" d="M0,0 l2,0 l-1,1 z" />
</g>
</svg>
</div>
Tested FF, Chrome, IE, Edge, mob Safari and mob Chrome
Another option would be to use background liner gradients, and flex positioning to make sure that the triangle always scales to its parent container. No matter how wide or narrow you make that container, the triangle always scales with it. Here is the fiddle:
https://jsfiddle.net/29k4ngzr/
<div class="triangle-wrapper-100">
<div class="triangle-left"></div>
<div class="triangle-right"></div>
</div>
.triangle-wrapper-100 {
width: 100%;
height: 100px;
display:flex;
flex-direction: column;
flex-wrap: wrap;
}
.triangle-right {
right: 0px;
background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
width: 50%;
height: 100px;
}
.triangle-left {
left: 0px;
background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
width: 50%;
height: 100px;
transform: scaleX(-1);
}
I took #Probocop's answer and come up with the following:
<style>
.btn {
background-color: orange;
color: white;
margin-bottom: 50px;
padding: 15px;
position: relative;
text-align: center;
text-decoration: none;
}
.btn:after {
background-color: inherit;
clip-path: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CclipPath id="p" clipPathUnits="objectBoundingBox"%3E%3Cpolygon points="0 0, 1 0, 0.5 1" /%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E#p'); /* fix for firefox (tested in version 52) */
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
content: '';
height: 50px;
left: 0;
position: absolute;
right: 0;
top: 100%;
}
</style>
Hello!
This works in Chrome and I've added a fix for Firefox. It doesn't work in Edge, however if you decrease the height of the down arrow then it doesn't look so bad.
Please note that if you are using bootstrap you will need to either change the name or override some of the styles it applies. If you decide to rename it then you also need to add the following to the .btn style:
box-sizing: content-box;

Resources