parallel and equidistant gaps on shapes / elements CSS [duplicate] - html

I want to create a shape, which i would describe as "inverse circle":
The image is somehow inaccurate, because the black line should continue along the outer border of the div element.
Here is a demo of what i have at the moment: http://jsfiddle.net/n9fTF/
Is that even possible with CSS without images?

Update: CSS3 Radial Background Gradient Option
(For those browsers supporting it--tested in FF and Chrome--IE10, Safari should work too).
One "problem" with my original answer is those situations where one does not have a solid background that they are working against. This update creates the same effect allowing for a transparent "gap" between the circle and it's inverse cutout.
See example fiddle.
CSS
.inversePair {
border: 1px solid black;
display: inline-block;
position: relative;
height: 100px;
text-align: center;
line-height: 100px;
vertical-align: middle;
}
#a {
width: 100px;
border-radius: 50px;
background: grey;
z-index: 1;
}
#b {
width: 200px;
/* need to play with margin/padding adjustment
based on your desired "gap" */
padding-left: 30px;
margin-left: -30px;
/* real borders */
border-left: none;
-webkit-border-top-right-radius: 20px;
-webkit-border-bottom-right-radius: 20px;
-moz-border-radius-topright: 20px;
-moz-border-radius-bottomright: 20px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
/* the inverse circle "cut" */
background-image: -moz-radial-gradient(
-23px 50%, /* the -23px left position varies by your "gap" */
circle closest-corner, /* keep radius to half height */
transparent 0, /* transparent at center */
transparent 55px, /*transparent at edge of gap */
black 56px, /* start circle "border" */
grey 57px /* end circle border and begin color of rest of background */
);
background-image: -webkit-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: -ms-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: -o-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
}
Original Answer
Took more effort than I expected to get the z-indexing to work (this seems to ignore the negative z-index), however, this gives a nice clean look (tested in IE9, FF, Chrome):
HTML
<div id="a" class="inversePair">A</div>
<div id="b" class="inversePair">B</div>
CSS
.inversePair {
border: 1px solid black;
background: grey;
display: inline-block;
position: relative;
height: 100px;
text-align: center;
line-height: 100px;
vertical-align: middle;
}
#a {
width: 100px;
border-radius: 50px;
}
#a:before {
content:' ';
left: -6px;
top: -6px;
position: absolute;
z-index: -1;
width: 112px; /* 5px gap */
height: 112px;
border-radius: 56px;
background-color: white;
}
#b {
width: 200px;
z-index: -2;
padding-left: 50px;
margin-left: -55px;
overflow: hidden;
-webkit-border-top-right-radius: 20px;
-webkit-border-bottom-right-radius: 20px;
-moz-border-radius-topright: 20px;
-moz-border-radius-bottomright: 20px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
#b:before {
content:' ';
left: -58px;
top: -7px;
position: absolute;
width: 114px; /* 5px gap, 1px border */
height: 114px;
border-radius: 57px;
background-color: black;
}

I can't really tell from your drawing how rounded you want the points, but here's one possibility:
http://jsfiddle.net/n9fTF/6/
If the points need to be more rounded, you'll need to put some circles on the ends so they blend with the big scoop.

Different approach : Box-shadows
This approach uses CSS box shadows which are supported by IE9+ (canIuse)
DEMO
Output :
HTML :
<div id="a">
<div id="b"></div>
</div>
CSS :
#a{
overflow:hidden;
border-radius:20px;
position:relative;
display:inline-block;
}
#a:before, #a:after{
content:'';
width: 100px;
border-radius: 50%;
}
#a:before {
height: 100px;
float:left;
border: 1px solid black;
background: grey;
}
#a:after {
position:absolute;
left:14px; top:-6px;
height:114px;
box-shadow: 1px 0px 0px 0px #000, 110px 0px 0px 68px #808080;
background:none;
z-index:-1;
}
#b {
width: 200px;
height: 100px;
background:none;
margin-left:-15px;
border: 1px solid black;
border-left:none;
float:left;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}

This is a very interesting question. I've recently posted a tutorial on how to make Inverse Border Radius in CSS (here) and I think this could easily be adapted for your case.
The trick is to create a span that generates the inverse border using a very simple concept - very thick borders. And use the inside section by hiding them. What you would have to do in addition to my script provided is add another border-radius to the top-left corner as I am only using the top-right one. Make the span aligned to the left of the item you want by absolute positioning, and increase the height/width of span accordingly and voila you have your inverse border-radius.

Using clip path this can be done .
let precision = 64;
let radius = 50;
let c = [...Array(precision)].map((_, i) => {
let a = -i/(precision-1)*Math.PI*2;
let x = Math.cos(a)*radius + 100;
let y = Math.sin(a)*radius + 50;
return `${x}% ${y}%`
})
document.querySelector('.circleContainer').style.clipPath =
`polygon(100% 50%, 100% 100%, 0 100%, 0 0, 100% 0, 100% 50%, ${c.join(',')})`;
.container{
display: flex;
position: relative;
width: 200px;
}
.left{
background: blue;
width: 100px;
height: 100px;
border-top-left-radius: 50%;
border-bottom-left-radius: 50%;
}
.circleContainer {
background: blue;
width: 100px;
height: 100px;
}
.innerCircle{
width: 80px;
height: 80px;
border-radius: 50%;
background: orange;
position: absolute;
top: 10px;
right: -40px;
}
<div class='container'>
<div class='left'></div>
<div class='circleContainer'></div>
<div class='innerCircle'></div>
</div>
Using an approah which I found here

Someone else done it somewhere from what I found...
JSFiddle: http://jsfiddle.net/ajeN7/
and the question: CSS3 Inverted Rounded Corner
Hopefully that helps!

Introduce an absolutely positioned borderless white circle which sits behind the gray circle at an offset. You will need to set the z-index of the dark circle to ensure that it sits above the white circle:
#c {
position: absolute;
border: 0;
left: 30px;
width: 100px;
height: 100px;
border-radius: 50px;
background: white;
}
Demo.
​

Related

How to I create an inverted border like this?

Image I'm able to achieve the top right border radius as per this design but for the left border I'm a bit confused.
.inverted-border-radius::before {
content: "";
position: absolute;
background-color: transparent;
bottom: 38px;
right: 0;
width: 20px;
height: 20px;
background: #d6dcea;
-webkit-mask-image: radial-gradient(
circle 10px at 0 0,
transparent 0,
transparent 20px,
black 21px
);
box-shadow: 0 -25px 0 0 #f66969;
}
This is css that I'm using. I know that some changes on radial-gradient will do the trick but getting really confused here.
apply border-bottom
.card {
width: 200px;
height: 50px;
border-radius: 5px;
border: 1px solid #dfe2e6;
border-bottom: 5px solid #2091bd;
}
<div class="card">
</div>

How to increase size of object upwards and maintain its shape?

I have the following CSS:
.tank {
position:relative;
width:12px;
height:18px;
background-color:#444;
}
.tank:before {
width: 12px;
height: 5px;
background-color:#666;
-moz-border-radius: 6px / 2.5px;
-webkit-border-radius: 6px / 2.5px;
border-radius: 6px / 2.5px;
position:absolute;
content:'';
top:-2.5px;
}
.tank:after {
width: 12px;
height: 5px;
background-color:#444;
-moz-border-radius: 6px / 2.5px;
-webkit-border-radius: 6px / 2.5px;
border-radius: 6px / 2.5px;
position:absolute;
content:'';
top:15.5px;
box-shadow:0px 0px 10px rgba(0, 0, 0, 0.75);
z-index: -1;
}
</style>
when I add it to my map it produces the following:
when I try to increase the size via the CSS the size is adjusted backwards (it goes downward not upwards).
I tried to fix it via the position and the height but still get the same down result.
Questions:
How can I have it adjusted upwards
Maintain the cylinder in the same shape (the base and the top should be rounded).
Is it possible to have a 'dynamic adjustment' say <div class="tank-20"></div> (means 20 height) and <div class="tank-80"></div> (= 80 in height).
jsfiddle
You can update your code like below:
.tank {
position: relative;
display:inline-block; /* this will make them stay at the bottom */
margin: 40px 10px;
width: 120px;
height: var(--w,180px);
background-color: #444;
border-radius: 60px / 25px;
}
.tank:before,
.tank:after{
border-radius: inherit;
position: absolute;
content: '';
width:100%;
height: 50px;
}
.tank:before {
background-color: #666;
top: 0;
}
.tank:after {
background-color: #444;
bottom:0;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.75);
z-index: -1;
}
<div class="tank"></div>
<div class="tank" style="--w:100px"></div>
<div class="tank" style="--w:200px"></div>
<div class="tank" style="--w:80px"></div>
Another idea. Hover to see the growing effect:
.tank {
position: relative;
display:inline-block;
margin: 40px 10px;
width: 120px;
/* big height here to illustarte,
you don't need it if you will place your element using position:absolute */
height: 300px;
}
.tank:before,
.tank:after{
position: absolute;
content: '';
width:100%;
height: 50px;
bottom: 0;
border-radius: 60px / 25px;
}
.tank:after {
background:
radial-gradient(50% 50%,#666 98%,transparent 100%) top/100% 50px no-repeat,
#444;
bottom:25px;
height:var(--w,180px);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
transition:0.5s;
}
.tank:before {
background-color: #444;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.75);
}
.tank:hover::after {
height:calc(1.5*var(--w,180px));
}
<div class="tank"></div>
<div class="tank" style="--w:100px"></div>
<div class="tank" style="--w:200px"></div>
<div class="tank" style="--w:80px"></div>
When you increase the height of the .tank you should increase the top property at .tank:after as well due to that you can not increase the height .tank and the size add upwards of the .tank the only solution to that is use right, left, top and bottom to adjust where your .tank should be just see an example on how I increased the height of the .tank an still have the cylinder shape
I increase height of .tank from 180px to 225px
and top of .tank:after from 155px to 200px
Example
.tank {
position: relative;
margin: 50px;
width: 120px;
height: 225px;
background-color: #444;
}
.tank:before {
width: 120px;
height: 50px;
background-color: #666;
-moz-border-radius: 60px / 25px;
-webkit-border-radius: 60px / 25px;
border-radius: 60px / 25px;
position: absolute;
content: '';
top: -25px;
}
.tank:after {
width: 120px;
height: 50px;
background-color: #444;
-moz-border-radius: 60px / 25px;
-webkit-border-radius: 60px / 25px;
border-radius: 60px / 25px;
position: absolute;
content: '';
top: 200px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.75);
z-index: -1;
}
<div class="tank"></div>

Adding shadow to trapezoid

First of all, this question might be similar to this, but the shape in my case is different, so it couldn't really help me out.
The trapezoid code is the following:
#light {
/*setting the element*/
border-bottom: 164px solid grey;
border-left: 148px solid transparent;
border-right: 165px solid transparent;
height: 0;
width: 80px;
}
<div id="light"></div>
Just to clarify, I am trying to add the shadow effect, similar to the following example:
#bulb {
/*setting the element*/
background: grey;
width: 200px;
height: 200px;
border-radius: 50%;
/*adding "light" (shadow)*/
box-shadow: 0 0 100px 10px rgba(128, 128, 128, 0.5);
}
<div id="bulb"></div>
When I try to add the regular box-shadow:, my trapezoid becomes a regular rectangle with white parts.
Instead of a box-shadow you could use a drop-shadow filter, e.g.
filter: drop-shadow(0 0 40px #222);
#light {
/*setting the element*/
border-bottom: 164px solid grey;
border-left: 148px solid transparent;
border-right: 165px solid transparent;
height: 0;
width: 80px;
filter: drop-shadow(0 0 40px #222);
}
<div id="light"></div>
More info on MDN
I would create the shape differently using pseudo element with a blur effect:
#light {
width:400px;
height:160px;
position:relative;
}
#light:before,
#light:after{
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:
/*triangle on the right*/
linear-gradient(to top right,grey 49.5%,transparent 50%) right/150px 100%,
/*triangle on the left*/
linear-gradient(to top left, grey 49.5%,transparent 50%) left /150px 100%,
/*rectangle at the center*/
linear-gradient(grey,grey) center/100px 100%;
background-repeat:no-repeat;
}
#light:before {
filter:blur(20px);
}
<div id="light">
</div>
based on css-tricks Double-Box Method you can "have a container box with hidden overflow and another box inside it which is rotate and hangs out of it"
.light {
width: 350px;
height: 135px;
position: relative;
overflow: hidden;
box-shadow: 0 16px 10px -17px rgba(0, 0, 0, 0.5);
}
.light:after {
content: "";
position: absolute;
width: 300px;
height: 300px;
background: #999;
transform: rotate(45deg);
top: 25px;
left: 25px;
box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5);
}
<div class="light"></div>
In your example, you can't add a proper box-shadow without having these white parts on each side. That is because the CSS border colouring the grey shaped trapeziod DIV.
In the example above, they are using an .SVG file (image), since it is an image, the original shape of it is a trapezoid, not a rectangle with white side like yours.
You will need to draw an .svg in the shape and color you want, and then add a shadow to the element itself.
Here are more informations about SVG.
I hope it helps.

CSS Responsive banner with oblique shadow

I'm trying to create a background for a banner using css where one side has a color and on the other side has another one with a 45° cut like this
I've been able to recreate the above image except for the drop shadow that doesn't stay in the right position.
Any advice would be greatly appreciated.
This is my code code:
#container {
height: 100px;
width: 400px;
overflow: hidden;
background-color: #2962ff;
}
#triangle-topleft {
width: 0;
height: 0;
border-top: 100px solid #2196f3;
border-right: 400px solid transparent;
-webkit-box-shadow: 5px 5px 20px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 20px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 20px 0px rgba(0,0,0,0.75);
}
<div id="container">
<div id="triangle-topleft"></div>
</div>
The CSS triangle trick with border can not be used for this, as a shadow will still be applied to the box, and not only to the triangle.
You will have to create a pseudo element, rotate it and THEN apply shadow to it.
#container {
position: relative;
height: 200px;
width: 200px;
overflow: hidden;
background-color: grey;
}
#container:before {
content: '';
position: absolute;
left: 20%;
width: 100%;
height: 200%;
background-color: rgb(255, 255, 255); /* fallback */
background-color: rgba(255, 255, 255, 0.5);
top: 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
box-shadow: inset 0 0 20px 10px #333;
}
<div id="container"></div>
Basically you create a rectangle which is larger than the parent, then rotate it and apply a shadow. You can tweak the colors and rotation-degree for your needs
Demo: http://jsfiddle.net/b5TnZ/2032/
You can add multiple color stops in Linear Gradients. Use two color set.
Gradient generated using Shapy
.canvas {
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
min-height: 100%;
min-width: 100%;
}
.gradient-canvas {
max-height: 100%;
max-width: 100%;
width: 100%;
height: 100%;
background: linear-gradient(127deg, rgb(31, 163, 209) 0%, rgb(31, 163, 209) 50%, rgb(25, 64, 208) 0%, rgb(46, 101, 223) 52%) 50% 50% / 100% 100% no-repeat;
}
<div class="canvas"><div class="gradient-canvas"></div></div>
You can try gradient like below:
#container {
height: 150px;
background:
linear-gradient(135deg,#2962ff 49.8%,rgba(0,0,0,0.75) 50%, #2196f3 calc(50% + 10px));
background-color:#2196f3;
}
<div id="container">
</div>
And simply replace the deg with to bottom right if you want the diagonal result:
#container {
height: 150px;
width:50%;
background:
linear-gradient(to bottom right,#2962ff 50%,rgba(0,0,0,0.75) 50%, #2196f3 calc(50% + 10px));
background-color:#2196f3;
}
<div id="container">
</div>

Transparent border radius outside

I need some help, I have a div with border-radius and I need it to be transparent outside the circle div. I tried with :after and outline. With ":after" the border stayed within the div and with outline I couldn't get it rounded.
Does anyone know the answer ?
CSS :
div.circle {
background: black;
width: 5em;
height: 5em;
-moz-border-radius: 2.5em;
-webkit-border-radius: 2.5em;
border-radius: 2.5em;
}
div.circle p {
padding: 2em 2em 0 2em;
color: white;
}
div.circle:after {
content:'';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: 2.5em;
border: 4px solid rgba(255, 255, 255, 0.51);
}
CSS with outline property:
div.circle {
outline: 4px solid rgba(255,255,255,0.3);
background: black;
width: 5em; height: 5em;
-moz-border-radius: 2.5em;
-webkit-border-radius: 2.5em;
border-radius: 2.5em;
}
What I want:
http://giovannigras.be/home/img.png
Use box-shadow instead of border:
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.51);
Cause a transparent border will transpare the background beneath,
while if you use the spread value in the box-shadow property you're good to go:
Example demo
Also as suggested by #vals you can go with background-clip to retain the background size into the content-box size model cause otherwise goes into the default border-box.
Docs:
https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow
https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip
If you want your border to be transparent (or semitransparent), and you are setting a black background, you need to set the background limited to the inner part, so that the border can be seen.
The property for this is background-clip: content-box;
CSS
div.circle {
background: black;
background-clip: content-box;
width: 5em;
height: 5em;
border-radius: 50%;
border: solid 5px rgba(0,0,0,0.3);
}
fiddle
You can use a container to provide a border offset if you need it.
DEMO
HTML
<div class="border">
<div class="inner"></div>
</div>
CSS
.border {
width: 80px; height: 80px;
border-radius: 50%;
background: transparent;
border: 10px solid rgba(255,255,255,.4);
}
.inner {
width: calc(100% - 40px);
height: calc(100% - 40px);
border-radius: 50%;
background: rgba(255,255,255,.6);
border: 10px solid transparent;
margin: 10px;
}