css - border on only a quarter of a circle shape? - css

I'm trying to create a rectangle with indented corners. So I have a relatively positioned rectangle with a colored background. I then absolutely positioned a circle in each corner, which gives the impression of indented corners on the rectangle. This works great as long as I keep the background color on the rectangle and circle are white, matching the page background.
But I'd like to have the background of the rectangle and circles both be white, matching the page background, and have borders on both of them. but when I do that, the rectangle's border appears around the circles. I've experimented with z-index, but that's not working. Any suggestions? Thank you.
Here is the relevant code:
<style>
#rect {width:200px; height: 300px;background-color: #fff;position: relative;overflow: hidden; border:1px solid #747474;}
.circle {border-radius: 50%; background-color: #fff; border: 1px solid #747474; width: 50px;height: 50px;position: absolute;}
.topleft {top: -10px;left: -10px;}
.topright {top: -10px;right: -10px;}
.bottomleft {bottom: -10px;left: -10px;}
.bottomright {bottom: -10px;right: -10px;}
</style>
</head>
<body>
<div id ="rect">
<div class ="circle topleft"></div>
<div class ="circle topright"></div>
<div class ="circle bottomleft"></div>
<div class ="circle bottomright"></div>
</div>

You can use
#rect {
border: none; // default value
}
#rect:before {
content: "";
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
border:1px solid #747474;
}
Demo
The problem is that with overflow: hidden, circles can't overlap #rect's border. Then, remove that border and add it to a pseudo-element instead.

Slightly different approach - FIDDLE.
CSS
#rect {
width:200px;
height: 300px;
position: relative;
overflow: visible;
border:1px solid #747474;
}
.circle {
border-radius: 50%;
background-color: white;
border: 1px solid white;
width: 100px;
height: 100px;
position: absolute;
z-index: 9999;
}
.topleft {
top: -52px;
left: -52px;
border-right-color: black;
transform: rotate(45deg);
}
.topright {
top: -52px;
left: 150px;
border-left-color: black;
transform: rotate(-45deg);
}
.bottomleft {
top: 250px;
left: -52px;
border-right-color: black;
transform: rotate(-45deg);
}
.bottomright {
top: 250px;
left: 150px;
border-top-color: black;
transform: rotate(-45deg);
}

Related

CSS: Circle with half one color and the other half another color?

Is it possible to do something like this with CSS? Basically make half the circle one color and the other half another color?
A linear-gradient will do that, and use border-radius to make it a circle.
div {
width: 50vw;
height: 50vw;
background: linear-gradient( -45deg, blue, blue 49%, white 49%, white 51%, red 51% );
border-radius: 50%;
}
<div></div>
You can do something like this:
div {
border-radius: 50px;
border-right-color: red;
border-top-color: blue;
border-bottom-color: red;
border-left-color: blue;
border-width: 50px;
border-style: solid;
height: 0px;
width: 0px;
}
<div>
</div>
You can use :before and :after pseudo-elements for each half of circle and also add transform: rotate() on parent element.
.circle {
display: inline-block;
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
transform: rotate(25deg);
}
.circle:after, .circle:before {
content: '';
position: absolute;
height: 100%;
width: 50%;
}
.circle:after {
background: #02FBFD;
left: -2px;
}
.circle:before {
background: #FE0103;
right: -2px;
}
<div class="circle"></div>

How to rotate pseudo element css

I want to recreate this icon using css pseudo elements (as a toggle indicator):
I have created the nececcary pseudo elements using ::after, ::before and tried to rotate them using transform: rotate(90deg).
How can I tell them to rotate around their own center? I have tried transform-origin: 50% 50%; which does not work. Right now, both pseudo elements got the same right: 10px; but they are not placed above each other, instead they are next to each other.
You can check this JS FIDDLE to illustrate the problem.
First you can use :before and :after pseudo elements and create shape like this DEMO
After that you can rotate parent element for 45deg and get desired result.
.el {
margin: 50px;
position: relative;
transform: rotate(45deg);
display: inline-block;
}
.el:before,
.el:after {
content: '';
width: 30px;
height: 30px;
position: absolute;
}
.el:before {
border-top: 4px solid black;
border-left: 4px solid black;
top: -10px;
left: -10px;
}
.el:after {
border-bottom: 4px solid black;
border-right: 4px solid black;
top: 10px;
left: 10px;
}
<div class="el"></div>
Update: You can also add some transition on :hover like this
.el {
margin: 50px;
position: relative;
transform: rotate(45deg);
display: inline-block;
cursor: pointer;
}
.el:before,
.el:after {
content: '';
width: 30px;
height: 30px;
position: absolute;
transition: all 0.3s ease-in;
}
.el:before {
border-top: 4px solid black;
border-left: 4px solid black;
top: -10px;
left: -10px;
}
.el:after {
border-bottom: 4px solid black;
border-right: 4px solid black;
top: 10px;
left: 10px;
}
.el:hover:before {
top: -15px;
left: -15px;
}
.el:hover:after {
top: 15px;
left: 15px;
}
<div class="el"></div>
transform-origin works fine, it's just that
a) 50% 50% (the object's center) is the default, and
b) you have to center the content of the box. That's a bit tricky because the icon you use doesn't require the full line height. Try adding
::before, ::after {
padding-bottom: .17em;
}
modify the style of #pseudo::after as right: 0;
#div {
background: blue;
width: 80px;
height: 80px;
transform: rotate(45deg);
}
/* tested but not working */
#pseudo::after,
#pseudo::before {
/* transform-origin: 50% 50%; */
}
#pseudo::after {
content: '›';
font-size: 50px;
color: green;
right: 0;
position: absolute;
transform: rotate(90deg);
top: 40px;
}
#pseudo::before {
content: '›';
font-size: 50px;
position: absolute;
color: green;
right: 10px;
top: 10px;
transform: rotate(-90deg);
}
<div id="div"></div>
<div id="pseudo"></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.

CSS to create an acute isosceles triangle with curved edges

I am trying to create a triangle using purely CSS which has curved edges.
Is this possible without it being totally over the top?
I've added an example below of what I'm trying to achieve (the curved lines - not the straight lines).
So far I have been working with the following code but it's not quite what I'm looking for.
#inner {
transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
-moz-transform: rotate(45deg);
background-color: silver;
width: 100px;
height: 100px;
top: 20px;
left: -50px;
position: relative;
-moz-border-radius: 20px;
border-radius: 20px;
}
#outer {
position: absolute;
width: 70px;
height: 140px;
top: 20px;
left: 50px;
overflow: hidden;
border: 1px solid red;
}
<div id="outer">
<div id="inner"> </div>
</div>
How about an svg solution?
<svg width="200" height="200" viewBox="-2 0 252 212">
<path fill="rosybrown" d="M125 0 c-81.6 60 -113.3 130 -125 200 c83.3 40 166.6 40 250 0 c-11.7 -70 -43.4 -140 -125 -200" fill="none" stroke-width="2" stroke="black" />
</svg>
Just another posibility, without using any rotation. Just clipping different circles.
.triangle {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background-color: lightblue;
overflow: hidden;
}
.triangle div {
position: absolute;
width: 100%;
height: 100%;
top: 31%;
left: 16%;
background-color: lightyellow;
border-radius: 50%;
overflow: hidden;
}
.triangle div:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
right: 30%;
background-color: red;
border-radius: 50%;
}
<div class="triangle">
<div></div>
</div>
The light colors are there just to make the construction of the triangle more visible
solution 1: Using two elements
The first example is not perfect, but does sort of answers your question:
.wrapper{
/*overflow:hidden;*/
width:0;
border-top:100px solid transparent;
border-left:100px solid red;
position:relative;
margin:50px;
transform:rotate(135deg);
}
.triangle{
width:20px;
height:100px;
background:red;
border-radius:50%;
transform:translate(-110px);
position:absolute;
top:-100px;
left:0;
}
.triangle:after{
content:"";
width:100px;
height:20px;
background:red;
border-radius:50%;
transform:translate(0px);
position:absolute;
top:90px;
left:10px;
}
.triangle:before{
content:"";
width:140px;
height:20px;
background:red;
border-radius:50%;
transform:rotate(225deg);
position:absolute;
top:40px;
left:-10px;
}
<div class="wrapper">
<div class="triangle"></div>
</div>
Please note This isn't an equilateral triangle, more of an isosceles one and could be edited into a better one no doubt!!
Solution 2: Using a single element
I was trying to create this shape using a single div element, but i was only able to generate two sides of the triangle. So, from this, I deduced that using css along requires two elements:
Two sides Of the Triangle Shown:
div {
border-left: 100px solid transparent;
border-bottom: 126px solid blue;
border-right: 100px solid transparent;
width: 0;
border-radius:50%;
position: relative;
}
div:after,
div:before {
content: "";
position: absolute;
height: 130px;
width: 20px;
border-radius: 50%;
top: -15px;
background: blue;
}
div:after {
left: -50px;
transform: rotate(40deg);
}
div:before {
left: 30px;
transform: rotate(-40deg);
}
<div></div>
I am guessing that svg may be a better option (note: I do not know svg, that seems like #chipChocolate.pys's area of expertise). So using 'just pseudo effects', I think you're looking to use two elements (but I'd like to see be proved wrong!). The 'single element' doesn't quite seem right, but may or may not be perfect for you
Pure CSS
Using different transforms.
I created three sectors using transform: rotate(30deg); and transform-origin: 0% 100%; Then I transformed their parent containers (scaleX: -1; for the left side). Done.
This can be done with just one pair of #cont and #circ elements, but I used different tags just for demonstrating better.
#cont {
height: 300px;
width: 300px;
overflow: hidden;
position:relative;
}
#circ {
height: 300px;
width: 300px;
background: black;
border-radius: 0 300px 0 0;
transform: rotate(30deg);
transform-origin: 0% 100%;
}
#cont:nth-of-type(2){
top: -300px;
transform: scaleX(-1);
}
#cont:nth-of-type(3){
top: -600px;
transform: rotate(30deg);
transform-origin: 0% 100%;
}
#cont:nth-of-type(3) > #circ {
border-radius: 0 0 300px 0;
transform-origin: 0% 0%;
}
<div id="cont">
<div id="circ">
</div>
</div>
<div id="cont">
<div id="circ">
</div>
</div>
<div id="cont">
<div id="circ">
</div>
</div>
Note: For a real website, almost always use SVG. But creating shapes with CSS is an art which mustn't be killed.
Here is my attempt at this. I think this is the best way to do it, using 1 element and :before :after.
Using the div as the base element (the bottom) we can line up the other 2 above it keeping the size and shape equal.
div {
width: 120px;
height: 60px;
background: red;
border-radius: 50%;
position: relative;
margin: 100px;
}
div:before, div:after {
content: "";
display: block;
background: red;
border-radius: 50%;
position: absolute;
width: 60px;
height: 120px;
top: -70px;
}
div:before {
transform: rotate(30deg);
left: 8px;
}
div:after {
transform: rotate(-30deg);
right: 8px;
}
<div></div>
Edit:
Another Attempt, slight tweaking from the first.
div {
width: 100px;
height: 50px;
background: red;
border-radius: 50%;
position: absolute;
top: 10px;
left: 70px;
margin: 100px;
}
div:before,
div:after {
content: "";
display: block;
background: red;
border-radius: 50%;
position: absolute;
width: 36px;
height: 106px;
top: -65px;
}
div:before {
transform: rotate(28deg);
left: 8px;
border-right: 10px solid red;
}
div:after {
transform: rotate(-28deg);
right: 8px;
border-left: 9px solid red;
}
<div></div>
I like the challenge :)
I recently have come to love the more complex border radius variations. I'm sure with some more fiddling and decent math calculations you can get rid of the rough edges where the different sides meet. No time for it now unfortunately.
.triangle {
position: absolute;
top: 100px;
left: 100px;
border-left: 25px solid transparent;
border-bottom: 40px solid blue;
border-right: 25px solid transparent;
width: 0;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(160deg);
}
.triangle:after {
content: '';
position: absolute;
border-left: 25px solid transparent;
border-bottom: 40px solid CornflowerBlue;
border-right: 25px solid transparent;
width: 0;
left: -54px;
top: -12px;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(120deg);
}
.triangle:before {
content: '';
position: absolute;
border-left: 25px solid transparent;
border-bottom: 40px solid darkblue;
border-right: 25px solid transparent;
width: 0;
top: -30px;
left: -29px;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(240deg);
}
<div class="triangle"></div>

Right trapezoid outline shape (with transparency)

I'm trying to emulate an angled path line similar to this image.
The way I'm doing it is using two trapezoid shapes, and overlapping one with another that would be the same as the background as seen in this jsFiddle.
But I realized I want the rest of the shape to be transparent instead of being able to overlap other objects.
The core is just a little bit of CSS, an outlineMaker div inside of a rightTrapezoid div.
.rightTrapezoid {
border-bottom: 100px solid red;
border-left: 0 solid transparent;
border-right: 50px solid transparent;
height: 0;
width: 100px;
}
.outlineMaker {
border-bottom: 80px solid white;
border-left: 0 solid transparent;
border-right: 40px solid transparent;
height: 20px;
width: 80px;
}
Is there a neat and concise way to do this?
Complete example following nice using #Feng Huo tip.
HTML Markup
<div class="trapezoidLine1">
<div class="trapezoidLine2"/>
</div>
<div class="trapezoidLine3">
<div class="trapezoidLine4"/>
</div>
CSS
.trapezoidLine1 {
position: absolute;
width: 200px;
height: 2px;
background: blue;
}
.trapezoidLine3 {
position: relative;
margin-top:45px;
width: 207px;
height: 2px;
background:blue;
}
.trapezoidLine2 {
position: absolute;
width: 47px;
height: 2px;
background: blue;
left: 200px;
-webkit-transform-origin: 0% 0%;
-webkit-transform: rotateZ(80deg);
}
.trapezoidLine4 {
position: absolute;
width: 45px;
height: 2px;
background: blue;
-webkit-transform-origin: 0% 0%;
-webkit-transform: rotateZ(270deg);
}
Try the fiddle
http://jsfiddle.net/TNW63/
Instead of trying to force this way to work with a twist somehow. I gave it a couple minutes of thought and realized DUHHHHHHH, I can just do this:
<div class="trapezoidLine1">
<div class="trapezoidLine2"/>
</div>
.trapezoidLine1 {
position: absolute;
width: 200px;
height: 10px;
background: blue;
}
.trapezoidLine2 {
position: absolute;
width: 200px;
height: 10px;
background: blue;
left: 200px;
-webkit-transform-origin: 0% 0%;
-webkit-transform: rotateZ(45deg);
}
Herp a derp...

Resources