How do I make a div triangle with concave left border? - css

I'm trying to make this shape in CSS. I haven´t been able to get it perfectly.

Check this out, I have done with the :before pseudo class. We can tweak the below snippet to make it look like what you need:
.triangle {
width: 0;
height: 0;
border-style: solid;
border-width: 50px 0 50px 86.6px;
border-color: transparent transparent transparent #f00;
}
.triangle:before {
display: block;
content: " ";
position: absolute;
height: 100px;
width: 10px;
left: 3px;
top: 8px;
background: #fff;
border-radius: 100%;
}
<div class="triangle"></div>
Another try:
.triangle {
width: 0;
height: 0;
border-style: solid;
border-width: 50px 0 50px 86.6px;
border-color: transparent transparent transparent #f00;
}
.triangle:before {
display: block;
content: " ";
position: absolute;
height: 180px;
width: 110px;
left: -90px;
top: -30px;
background: #fff;
border-radius: 200%;
}
<div class="triangle"></div>

This solution relies soley on CSS generated content, meaning no extra markup. The only caveat, is that ::after background color must match parent element background color.
div::before {
content:'';
position:absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 50px 0 50px 100px;
border-color: transparent transparent transparent #007bff;
}
div::after{
content:'';
display:block;
width:50px;
background:#fff;
height:100px;
position:absolute;
border-radius:0 100% 100% 0;
transform: scaleX(0.4);
transform-origin:top left;
}
Demo here

Related

How to change shape from pointing to top to point to right

I want to change the shape of the CSS from pointing to top to point to right. This is what I have now:
And this is what I want to have:
This is my current CSS:
.base {
background: red;
display: inline-block;
height: 55px;
margin-left: 20px;
margin-top: 55px;
position: relative;
width: 100px;
}
.base: before {
border-bottom: 35px solid red;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
content: "";
height: 0;
left: 0;
position: absolute;
top: -35px;
width: 0;
}
Please with below CSS
.base{
background: red;
display: inline-block;
height: 60px;
margin-left: 20px;
margin-top: 55px;
position: relative;
width: 100px;
}
.base:before {
border-left: 30px solid red;
border-top: 30px solid transparent;
border-bottom:30px solid transparent;
content: "";
height: 0;
left:100%;
position: absolute;
top:0;
width: 0;
}
It is simpler nowadays to use the CSS clip path facility rather than have to use borders and pseudo elements.
Clip path let’s you define a polygon in terms of percentages which means it is good for responsiveness, altering automatically to fit the dimensions of the element.
Here’s an example. Change the % values to suit the look you want.
.shape {
width: 200px;
height: 200px;
clip-path: polygon(0% 0%, 50% 0%, 100% 50%, 50% 100%, 0% 100%);
background: red;
}
<div class="shape"></div>
Caveat: not supported in IE

Create this shape in CSS (half pipe shape)

I've been trying to make this shape in CSS, but unfortunately could not find a way how to. It's half pipe like shaped:
The pixelated corner should be smooth (it's a zoomed in image).
Anyone knows how to create this? Or can get me on the right tracks?
You will need to use pseudo element :after for the inner block and then apply border-radius for curved corner.
div {
height: 60px;
width: 60px;
border: solid red;
position: relative;
background: red;
border-width: 0 10px 10px 0;
box-sizing: border-box;
}
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-bottom-right-radius: 10px;
background: #fff;
}
<div></div>
simple
.shape {
width: 140px;
height: 200px;
background-color: gray;
}
.shape:after {
content: '';
position: absolute;
width: 100px;
height: 160px;
background-color: #fff;
border-bottom-right-radius: 50px;
}
<div class="shape"></div>
I assume that the problem here is to create the "outer" curve, on the arbitrary background. It's achievable by the trick with clipping the needed part from the thick rounded border of the pseudo-element:
div {
width: 50%;
min-height: 4em;
margin: auto;
border: #888 solid;
border-width: 0 1em 1em 0;
position: relative;
}
div::after {
content: '';
border: #888 solid;
border-width: 0 1em 1em 0;
border-radius: 0 0 100% 0;
position: absolute;
right: -1em;
bottom: -1em;
width: 1em;
height: 1em;
clip: rect(0 1em 1em 0);
}
div:hover::after {
border-color: red; /* highlight the curved part */
}
body {
/* just as a background example */
background: repeating-linear-gradient(-45deg, #ddd, #ddd 1px, transparent 1px, transparent 10px);
min-height: 90vh;
}
<div></div>
You can do this with one element and with transparency like this:
.box {
width:80px;
height:100px;
border-right:20px solid grey;
border-bottom:20px solid grey;
box-sizing:border-box;
background:
radial-gradient(farthest-side at top left,transparent 98%,grey ) bottom right/20px 20px no-repeat;
}
body {
background:pink;
}
<div class="box">
</div>

Create div with triangle border in css

I am trying to create a div with arrow on left and right. No background, only border. Something like this:
I am able to create similar div with filled background color using ::before and ::after tags. However, only borders is something i am not able to achieve. Can it be done with css only?
https://jsfiddle.net/1g16x8p7/1/
html:
<div class="wizard">
<a class="item">
</a>
</div>
css:
.item {
display: inline-block;
padding: 15px;
padding-left: 25px;
/*default styles*/
background-color: green;
position: relative;
}
.item:before,
.item:after {
content: "";
height: 0;
width: 0;
border-width: 15px 0 15px 10px;
border-style: solid;
position: absolute;
left: 100%;
top: 0;
}
.item:before {
border-color: transparent transparent transparent white;
left: 0;
}
.item:after {
border-color: transparent transparent transparent green;
}
You can use ::before and ::after with borders on two adjacent sides (e.g. top and right) and then transform: rotate and position: absolute them to create the left and right parts, e.g.
<div class="arrow"></div>
.arrow {
height: 75px;
width: 200px;
border-top: 4px solid black;
border-bottom: 4px solid black;
position: relative;
}
.arrow::before, .arrow::after {
content: "";
border-top: 4px solid black;
border-right: 4px solid black;
height: 55px;
width: 55px;
position: absolute;
transform: rotate(45deg);
}
.arrow::before {
top: 8px;
left: -30px;
}
.arrow::after {
top: 8px;
right: -30px;
}
Here's an example.

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>

Trying to round part of shape

I know you can use border-radius to round objects with CSS, but I am trying to figure out how to round, or possibly hide, the pointed parts of a CSS shape when overlaying over a circle:
It's tough to explain without a Codepen:
http://codepen.io/cavanflynn/pen/gpEdJo
#circle:before {
position:absolute;
left: -10px;
top: -25px;
z-index: 100;
content: "";
border-right: 35px solid white;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid transparent;
}
In the Codepen you can see the circle and where parts of the white are overflowing the red boundary of it. The goal is to get rid of the white points and round the white perfectly with the red OR make the section of the circle that the white overlays completely transparent (like taking a slice from a pizza).
You can achieve this using a pseudo element, and using borders on the pseudo to manipulate the shape to your liking. This uses the transparent border color on the right side, with the rest with a solid color. A demo of this is shown below:
html {
background: url(http://lorempixel.com/800/900);
}
div {
position: relative;
height: 100px;
width: 100px;
border-radius: 50%;
background: gold;
margin: 150px auto;
}
div:before {
content: "";
position: absolute;
top: -50px;
left: -50px;
height: 100%;
width: 100%;
border-radius: 50%;
border: 50px solid red;
border-right-color: transparent;
}
<div></div>
If the angle here is too big for your liking, you could duplictate the pseudo element on an :after element, and using transform:rotate(x deg); to rotate to a specific angle
A demo of this can be seen when hovering below:
html {
background: url(http://lorempixel.com/800/900);
}
div {
position: relative;
height: 100px;
width: 100px;
border-radius: 50%;
background: gold;
margin: 150px auto;
}
div:before, div:after {
content: "";
position: absolute;
top: -50px;
left: -50px;
height: 100%;
width: 100%;
border-radius: 50%;
border: 50px solid red;
border-right-color: transparent;
transition:all 0.8s;
}
div:hover:after{
transform:rotate(45deg);
}
div:hover:before{
transform:rotate(-45deg);
}
<div></div>
Why does border-radius not work for my case?
Yes, border-radius property can be used to produce circles but it can produce a proper circle only when the height and width are the same. In your original sample, the height and width of the element is determined by the thickness of the border on the ::before element and since the border on one side is thicker than the rest, it produces a rectangle instead of a square. Because of this you would only get a oval at best and not a circle.
Even if you make the border thickness the same, the curvature of the round wouldn't match with the curvature of the outer circle (parent container) because the radii and center points are both different.
I have changed the border-color of the other three borders in the below snippet to help you visualize what is going on:
body {
background-color: black;
}
#circle {
border-right: 50px solid red;
border-left: 50px solid red;
border-top: 50px solid red;
border-bottom: 50px solid red;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
position: absolute;
left: 35px;
z-index: 100;
top: 50px;
}
#circle:after {
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
position: absolute;
left: -25px;
top: -25px;
z-index: 100;
content: "";
border: 25px solid yellow;
}
#circle:before {
position: absolute;
left: -10px;
top: -25px;
z-index: 101;
content: "";
border-right: 35px solid white;
border-top: 25px solid cyan;
border-bottom: 25px solid cyan;
border-left: 25px solid cyan;
border-radius: 50%;
}
<div id="circle"></div>
One other method that is typically used to cut out the extraneous part is overflow: hidden but that also wouldn't work for your case because your outer circle is created only by border and it doesn't actually have any content height or content width. Because of this when you add overflow: hidden your pseudo elements would get totally hidden.
What are the other options that I could use?
Here is an alternate approach to create the same shape as you originally intended to with just a single element + two pseudo-elements.
The shape consists of the following components:
A container element which is converted into a circle by using border-radius: 50%.
One pseudo-element with dimensions half that of the parent and border-radius: 50% to produce the inner circle. A z-index: 1 is added to position this above the sliced area.
Another pseudo-element which has a transform: rotate(45deg) added to produce the slice.
Parent container has overflow: hidden which prevents the other parts of the pseudo-element from showing up.
Note: I assume you won't be having any concerns using transform because you had tagged CSS3.
body {
background-color: black;
}
#circle {
position: relative;
height: 200px;
width: 200px;
background: red;
border-radius: 50%;
overflow: hidden;
}
#circle:before, #circle:after {
position: absolute;
content: '';
height: 100px;
width: 100px;
}
#circle:before {
top: 25%;
left: 25%;
background: yellow;
border-radius: 50%;
z-index: 1;
}
#circle:after {
right: 0px;
background: white;
transform: rotate(45deg);
transform-origin: left bottom;
}
<div id="circle"></div>
How to get a transparent slice? (like the Colorado flag)
Alternately, if you want the slice to be transparent totally then you can use the below approach:
Here the container has a bit of padding and the background of the container is made small by restricting it to only the content-box using background-clip. This forms the inner yellow circle.
The outer red circle is made up of two pseudo-elements each of which have a background color only for half portion through linear-gradient. The other half is transparent.
The two pseudo-elements are rotated in opposing directions to make it look as though they leave a transparent cut in between.
body {
background-image: linear-gradient(to bottom, rgb(64, 64, 150) 33%, white 33%, white 66%, rgb(64, 64, 150) 66%);
background-repeat: no-repeat;
height: 260px;
}
#circle {
position: relative;
height: 100px;
width: 100px;
background: rgb(255, 243, 21);
border-radius: 50%;
padding: 50px;
margin-top: 60px;
margin-left: 50px;
background-clip: content-box;
}
#circle:after,
#circle:before {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 200px;
width: 200px;
border-radius: 50%;
z-index: -1;
}
#circle:before {
background: linear-gradient(to bottom, rgb(237, 51, 56) 50%, transparent 50%);
transform: rotate(-45deg);
}
#circle:after {
background: linear-gradient(to top, rgb(237, 51, 56) 50%, transparent 50%);
transform: rotate(45deg);
}
<div id="circle"></div>
If you don't want to use linear-gradient to produce semi-circles then you can create the same effect by using two pseudo-elements whose height is half their width and assign the appropriate border-radius to it.
body {
background-image: linear-gradient(to bottom, rgb(64, 64, 150) 33%, white 33%, white 66%, rgb(64, 64, 150) 66%);
background-repeat: no-repeat;
height: 260px;
}
#circle {
position: relative;
height: 100px;
width: 100px;
background: rgb(255, 243, 21);
border-radius: 50%;
padding: 50px;
margin-top: 60px;
margin-left: 50px;
background-clip: content-box;
}
#circle:after,
#circle:before {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 100px;
width: 200px;
background: rgb(237, 51, 56);
border-radius: 100px 100px 0px 0px;
transform-origin: 50% 100%;
z-index: -1;
}
#circle:before {
transform: rotate(-45deg);
}
#circle:after {
bottom: 0px;
transform: rotate(225deg);
}
<div id="circle"></div>
You can change the approach. Stop using :before and :after, and use overflow: hidden plus z-index layering with multiple elements.
The new HTML:
<div class="circle">
<div class="inner-circle"></div>
<div class="triangle"></div>
</div>
The CSS:
.circle {
width: 200px;
height: 200px;
background: red;
position: relative;
top: 40px;
border-radius: 50%;
overflow: hidden;
z-index: 10;
}
.inner-circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: black;
top: 50px;
left: 50px;
position: relative;
z-index: 10;
}
.triangle {
position:absolute;
left: 25px;
top: 25px;
border-right: 105px solid purple;
border-top: 75px solid transparent;
border-bottom: 75px solid transparent;
border-left: 75px solid transparent;
z-index: 9;
}
Check the demo: https://jsfiddle.net/ghv02ucr/1/
I've checked on your question, try this code on your #circle:before, and you will see the triangle aligned;
#circle:before {
position:absolute;
left: -18px;
top: -25px;
z-index: 100;
content: "";
border-right: 35px solid white;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid transparent;
}
Or you can eliminate all the #circle:before properties to get rid of the triangle.... hope it helped.

Resources