I've read this great question already Transparent hollow or cut out circle
but I want to draw more circles (let's say three).
So I tried using an extra element for the circle instead of a pseudo-element (so I can add more) and it works for one circle but not for more. The problem is that they are not transparent since the last one covers everything. Here is my attempt:
body{
background-color:violet;
}
.shape{
height: 150px;
width: 150px;
position:relative;
overflow:hidden;
}
.hole{
position:absolute;
border-radius:100%;
width:30px; height:30px;
color:red;
box-shadow: 0px 0px 0px 2000px black;
}
.hole:nth-child(1) {
left:25px; top:25px;
}
.hole:nth-child(2) {
left:65px; top:25px;
}
.hole:nth-child(3) {
left:55px; top:65px;
}
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
Just use an svg. Black part of mask is removed from the element it is applied to and white is kept:
html, body {
height: 100%;
margin: 0;
background: linear-gradient(to top, red, blue);
}
svg {
display: block;
width: 150px;
}
<svg viewBox="0 0 150 150">
<mask id="circles" maskUnits="objectBoundingBox">
<rect x="0" y="0" width="100%" height="100%" fill="white" />
<circle cx="40" cy="40" r="15" fill="black" />
<circle cx="80" cy="40" r="15" fill="black" />
<circle cx="70" cy="80" r="15" fill="black" />
</mask>
<rect x="0" y="0" width="100%" height="100%" fill="green" style="mask: url(#circles)" />
</svg>
If you really want to make this with CSS and if you aren't afraid of multiple box-shadows, you could do this BUT you must be aware that this is hard coded and the values for box-shadow must be updated when the cirlces change position, size or number.
Here is an example of the approach you can use, the values for box shadow should be "optimized" :
body {
background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;
}
.shape {
height: 150px;
width: 150px;
position: relative;
overflow: hidden;
}
.hole {
position: absolute;
border-radius: 100%;
width: 30px;
height: 30px;
color: red;
}
.hole:nth-child(1) {
left: 25px;
top: 25px;
box-shadow: -38px -33px 0px 55px black, 9px 14px 0px 0px black;
}
.hole:nth-child(2) {
left: 65px;
top: 25px;
box-shadow: 76px -63px 0px 100px black, -7px 6px 0px 0px black;
}
.hole:nth-child(3) {
left: 55px;
top: 65px;
box-shadow: -3px 91px 0px 100px black;
}
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
Other than that, I would clearly recomend using SVG either with masking/clipping or with a path as shown in the answer you linked to. Here is an example with several cut out transparent circles using the path element with the arc command :
body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
svg{
display:block;
width:70%;
height:auto;
margin:0 auto;
}
path{
transition:fill .5s;
fill:#E3DFD2;
}
<svg viewbox="-10 -1 30 15">
<path d="M-10 -1 H30 V15 H-10z
M 5 5 m -5, 0
a 5,5 0 1,0 10,0
a 5,5 0 1,0 -10,0
M-3 10 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0
M15 8 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0
M-5 5 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0"/>
</svg>
The above code is fomarted so each circle in the path element is "drawn" with :
M cx cy m -r, 0
a r,r 0 1,0 (r * 2),0
a r,r 0 1,0 -(r * 2),0
The center of the circle is cx, cy and r is its radius. See this answer for an explanation.
The first line (M-10 -1 H30 V15 H-10z) is made to make the surounding rectangle and each cirlce "cuts it out".
The advantage of this approach is that it works for all browsers that support inline svg. Even those who don't support masking or clipping.
To understand how this works, you should take a look at :
SVG in HTML (inline)
the path command
and specificaly the arc command
You can use the rgba color values specifying opacity instead of using a single color for your box-shadow to have the desired effect.
Try box-shadow: 0px 0px 0px 2000px rgba(0, 0, 0 , 0.1);
<!DOCTYPE html>
<html>
<head>
<style>
.shape{
height: 150px;
width: 150px;
position:relative;
overflow:hidden;
background-color:#333333;
}
.hole{
position:absolute;
border-radius:20px;
width:20px;
height:20px;
color:red;
background-color:white;
opacity:0.6; /* for transparency levels change between 0=invisible and 1=opaque */
text-align:center;
}
.hole:nth-child(1) {
left:25px; top:25px;
}
.hole:nth-child(2) {
left:65px; top:25px;
}
.hole:nth-child(3) {
left:55px; top:65px;
}
</style>
</head>
<body>
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
</body>
</html>
Related
I am thinking how to style a squizzed box like this:
I found that I can achieve a similar result with pseudo elements and border-radius as percentage.
Here is the CodePen: https://codepen.io/micu22/pen/eYzpmqR
And here is the code:
div {
background: lightblue;
padding: 10px 20px;
border-radius: 8px;
position: relative;
}
div::after,
div::before {
content: "";
position: absolute;
background: white;
width: 100%;
height: 20px;
left: 0;
}
div::before {
top: -17px;
border-radius: 50%;
}
div::after {
bottom: -17px;
border-radius: 50%;
}
But maybe there is an easier or just more elegant solution?
I would do it like below, using gradient coloration and an SVG filter:
.box {
width:200px;
height:250px;
background:
/* v-- adjust the 15% here */
radial-gradient(50% 15% at top, transparent 98.5%,lightblue) top,
radial-gradient(50% 15% at bottom,transparent 98.5%,lightblue) bottom;
background-size:100% 51%;
background-repeat:no-repeat;
filter: url('#goo');
}
<div class="box"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs> <!-- adjust the the 13 here --v -->
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="13" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
It depends on how the content is going to exist. If this is a fixed height container, I'd probably opt for a solution using an SVG background.
I think the most elegant (or at least intrinsic) solution would involve using clipping paths. This would allow you to create an SVG of the exact shape you want and clip the container or background image for the container so that you aren't disguising a still technically visible part of the element.
Clippy is a great tool if you've never worked with clipping masks before.
I have tried put two svg element to create a hollow mask. And I want to create the effect like clip-path inset, but the result doesn't work. How can I solve this? Or are there any ways to achieve same effect?
https://codepen.io/penny289/pen/Exvaeaq?editors=1000
body{margin:0}
.aurora{
width:100vw;
height:100vh;
}
.move1,.move2,.move3{
position: absolute;
width: 1px;
height: 1px;
border-radius: 100%;
opacity: 0.7;
border-radius:2%;
z-index:-2;
}
.move1{
box-shadow: 0 0 35vmax 35vmax #0D8BD9;
}
.move2{
box-shadow: 0 0 35vmax 35vmax #0ff;
}
.move3{
box-shadow: 0 0 35vmax 35vmax #94D7F2;
}
<div class="aurora">
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<mask id="mask1">
<path fill="black" d="M51,-41.9C63.3,-25.1,68.8,-4.1,65.3,16.4C61.8,37,49.5,57,33.3,62C17.1,67.1,-2.8,57.2,-24.3,47.8C-45.8,38.5,-68.9,29.7,-74.5,14.3C-80.2,-1.1,-68.5,-23.2,-53.2,-40.7C-37.9,-58.1,-19,-70.8,0.2,-70.9C19.3,-71.1,38.6,-58.6,51,-41.9Z" />
</mask>
<rect width="100vw" height="100vh" fill="white" mask="url(#mask1)"></rect>
</svg>
<div class="move1"></div>
<div class="move2"></div>
<div class="move3"></div>
</div>
A mask is just masking off everything by default - the same as creating a mask with a black rectangle that is 100% in height and width. You path has a black fill, so black+black is still a 100% black mask.
I added a white rectangle in the mask, so that you can see the difference between masking with black/white.
And then your path was a bit off to the left/top, so I did a translate to place it inside the SVG viewbox.
body{margin:0}
.aurora{
width:100vw;
height:100vh;
}
.move1,.move2,.move3{
position: absolute;
width: 1px;
height: 1px;
border-radius: 100%;
opacity: 0.7;
border-radius:2%;
z-index:-2;
}
.move1{
box-shadow: 0 0 35vmax 35vmax #0D8BD9;
}
.move2{
box-shadow: 0 0 35vmax 35vmax #0ff;
}
.move3{
box-shadow: 0 0 35vmax 35vmax #94D7F2;
}
<div class="aurora">
<svg viewBox="0 0 200 200" width="400" xmlns="http://www.w3.org/2000/svg">
<mask id="mask1">
<rect width="100%" height="100%" fill="white"/>
<path transform="translate(90 80)" fill="black" d="M51,-41.9C63.3,-25.1,68.8,-4.1,65.3,16.4C61.8,37,49.5,57,33.3,62C17.1,67.1,-2.8,57.2,-24.3,47.8C-45.8,38.5,-68.9,29.7,-74.5,14.3C-80.2,-1.1,-68.5,-23.2,-53.2,-40.7C-37.9,-58.1,-19,-70.8,0.2,-70.9C19.3,-71.1,38.6,-58.6,51,-41.9Z" />
</mask>
<rect width="100vw" height="100vh" fill="white" mask="url(#mask1)"></rect>
</svg>
<div class="move1"></div>
<div class="move2"></div>
<div class="move3"></div>
</div>
I have two arrow images (previous / next) with the code here like this:
.fp-controlArrow {
position: absolute;
width: 32px; /* This can be added here so you don't have to set a width and height 2 times for each arrow, this will create one width for both arrows */
height: 32px; /* This does the same as above */
margin-top:-15px; /* This value must always be half of the height - This does the same as above */
z-index: 30;
top: 50%;
cursor: pointer;
}
.fp-controlArrow.fp-prev {
left:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e923133f8dc0bf994fc49_left-arrow.svg) no-repeat;
}
.fp-controlArrow.fp-next {
right:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e9231ec03b6c9682b540c_right-arrow.svg) no-repeat;
I would like when I hover over an arrow it a round transparent circle appeared behind the arrow like on this example:
enter image description here
how can I achieve this?
thank you!
padding: 1em;
border-radius: 50%;
background-color: rgba(200,200,200,0.5)
Add those lines to the .fp-controlArrow class That should do it.
Edit
Sorry, I didn't realize it was svg. You will have to inline the svg.
<div class="fp-controlArrow fp-prev">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-reactroot="">
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="1" stroke="#221b38" d="M16 20L8 12L16 4"></path>
</svg>
</div>
<div class="fp-controlArrow fp-next">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-reactroot="">
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="1" stroke="#221b38" d="M8 20L16 12L8 4"></path>
</svg>
</div>
.fp-controlArrow {
position: absolute;
width: 32px; /* This can be added here so you don't have to set a width and height 2 times for each arrow, this will create one width for both arrows */
height: 32px; /* This does the same as above */
margin-top:-15px; /* This value must always be half of the height - This does the same as above */
z-index: 30;
top: 50%;
cursor: pointer;
padding: 1em;
border-radius: 50%;
}
.fp-controlArrow:hover {
background: green;
background-color: rgba(200,200,200,0.5);
}
.fp-controlArrow.fp-prev {
left:0;
}
.fp-controlArrow.fp-next {
right:0;
Here is a codepen that demonstrates it.
Sorry, I didn't saw the space between : and hover.
.fp-controlArrow.fp-prev {
left:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e923133f8dc0bf994fc49_left-arrow.svg) no-repeat;
border-radius: 50px;
}
.fp-controlArrow.fp-prev:hover{
background-color: #999999;
}
I want the above result, cant use the image because the height of the div is not fixed.
Any help will be appriciated.
You can use pseudo classes & gredient background to creating this. check updated snippet below ...
.msgBox {
padding: 3px;
background: #f9db31;
background: -webkit-linear-gradient(#f9db31 0%, #ff0000 100%);
background: -moz-linear-gradient(#f9db31 0%, #ff0000 100%);
background: -o-linear-gradient(#f9db31 0%, #ff0000 100%);
background: linear-gradient(#f9db31 0%, #ff0000 100%);
float: left;
margin: 50px;
position: relative;
border-radius: 5px;
}
.msgBox::before {
border-bottom: 30px solid transparent;
border-right: 30px solid #f9db31;
border-top: 0 solid transparent;
content: "";
height: 0;
left: -27px;
position: absolute;
top: 25px;
width: 0;
z-index: 999;
}
.msgBox::after {
border-bottom: 28px solid transparent;
border-right: 28px solid #fff;
border-top: 0 solid transparent;
content: "";
height: 0;
left: -21px;
position: absolute;
top: 27px;
width: 0;
z-index: 999;
}
.innerBox {
width: 400px;
min-height: 200px;
background: #fff;
border-radius: 5px;
}
<div class="msgBox">
<div class="innerBox">
</div>
</div>
SVG can be used to create such shapes. It offers simplicity and scale-ability.
However in case your case as you need flexible height element, may
be it doesn't fit your needs. I'm leaving my answer here for a possible alternate for some similar situations where it might be handy.
We can use SVG's path element to create a shape like above and stroke / fill it with some solid color, gradient or a pattern.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Following code will create the above shape:
<path d="M0,25 L25,30 V20
Q25,5 40,5 L460,5
Q475,5 475,20 L475,170
Q475,185 460,185 L40,185
Q25,185 25,170 L25,50 Z" />
Below is a brief description of path commands used in above code:
M command is used to define the starting point. It appears at the beginning and specify the point from where drawing should start.
L and V commands are used to draw straight lines.
Q command is used to draw curves.
Z command is used to close current path. It draws a straight line from current point to the starting point to close the shape.
Output Image:
Working Example:
body {
padding: 10px;
}
<svg width="500" height="200" viewBox="0 0 500 200">
<defs>
<linearGradient id="grad" x2="0" y2="1">
<stop offset="0" stop-color="yellow" />
<stop offset="0.5" stop-color="orange" />
<stop offset="1" stop-color="red" />
</linearGradient>
</defs>
<path d="M0,25 L25,30 V20
Q25,5 40,5 L460,5
Q475,5 475,20 L475,170
Q475,185 460,185 L40,185
Q25,185 25,170 L25,50 Z" stroke="url(#grad)" stroke-width="2" fill="none" />
</svg>
Useful Resources:
Below are some useful links for SVG:
Specification
MDN
I am trying to make .main-div like this image
.main-div {
width: 100px;
height: 100px;
background-color: Red;
border-radius: 30px/20px;
}
<div class="main-div"></div>
My JSFiddle is here.
You can do a trick using a pseudo element and achieve that shape
body {
background: lightgray;
}
.main-div {
position: relative;
display: inline-block;
width: 110px;
height: 100px;
background-color: red;
border-radius: 30%/50%;
background: url(https://i.stack.imgur.com/CWoXa.png) center center no-repeat;
background-size: 110px 110px;
}
.main-div::after {
content: '';
position: absolute;
left: 5px;
top: -5px;
width: 100px;
height: 110px;
background: inherit;
background-size: inherit;
border-radius: 50%/30%;
}
.main-div+.main-div {
background: gray;
}
<div class="main-div"></div>
<div class="main-div"></div>
As Justinas remarked in their answer, the border of your example image does not look like it can be recreated with border-radius alone. This is because the outline is not an ellipse.
It is possible to do this, with good browser support, using SVG as follows.
/* set size of and center SVG */
svg {
display: block;
width: 200px;
height: 200px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
</defs>
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</svg>
This uses clipping in SVG with the clipPath element. You can define any path to use for the clipping. I have used four Bezier curves here. You can tweak where the control points are, or change this to use something entirely different if you wish.
An extra bonus of this approach is that it is now easy to apply other (advanced) filters, for example blurring the image or applying a drop shadow.
/* set size of and center SVG */
svg {
display: block;
width: 204px;
height: 204px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
<filter id="dropshadow" x="-30%" y="-30%"
width="160%" height="160%"
color-interpolation-filters="sRGB">
<!-- define color of shadow here -->
<feComponentTransfer in="SourceAlpha">
<feFuncR type="linear" slope="0"
intercept="0.518"></feFuncR>
<feFuncG type="linear" slope="0"
intercept="0.698"></feFuncG>
<feFuncB type="linear" slope="0"
intercept="0.867"></feFuncB>
</feComponentTransfer>
<!-- define blur of shadow here -->
<feGaussianBlur stdDeviation="2" />
<!-- we can offset the shadow -->
<feOffset result="shadow" dx="1" dy="1" />
<!-- put shadow below original content -->
<feBlend in="SourceGraphic"
in2="shadow" mode="normal" />
</filter>
</defs>
<g transform="translate(2, 2)"
filter="url(#dropshadow)">
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</g>
</svg>
Your image radius does not look like standard CSS border radius. If yes, than you need to use image preprocessing (in back-end side, e.g. GD or stand-alone tool like Photoshop) or use Clipping Mask with limited support. Using border radius you can have similar effect.
.main-div {
width: 100px;
height: 100px;
background-color: red;
border-radius: 40%;
overflow: hidden;
position: relative;
}
.main-div img {
width: 100%;
position: absolute;
left: -50px;
top: -50px;
margin-top: 50%;
margin-left: 50%;
}
<div class="main-div">
<img src="http://lorempixel.com/200/200/"/>
</div>
Add this style. You can change border-radius as per your requirements:
div {
border: 2px solid #a1a1a1;
padding: 10px 15px; `enter code here`
background: #dddddd;
width: 100px;
border-radius: 55px;
}
.element {
border-radius: 50px;
overflow: hidden;
}
<img src="https://image.ibb.co/irvmO5/html5.png" alt="html5" border="0" class="element"><br /><a target='_blank' href='https://imgbb.com/'>Rounded rectangle clip mask</a>