clip-path:circle() radius doesn't seem to be calculated correctly
It's defined to be like that, they never meant to calculate the radius you are showing. It's also in the specification.
To better understand let's consider a square. You can have a perfect circle if you consider 50%
as value
.red {
width: 200px;
height: 200px;
background: red;
clip-path: circle(50%);
border:2px solid;
box-sizing:border-box;
}
<div class='red'></div>
Make a perfect circle around a div of variable height
Clip-path
can easily do this if you consider solid coloration.
Resize the element and the circle will follow:
.box {
width: 200px;
height: 200px;
overflow: hidden;
resize: both;
background: blue;
box-shadow: 0 0 0 200vmax red;
clip-path: circle(71%);
margin: 100px auto;
}
<div class="box"></div>
How to add border in my clip-path: polygon(); CSS style
Can border be applied to a clipped element along the clip path?
No, adding border
property to the clipped element would not apply the borders along the clipped path because the border
is applied to the original rectangle (or square) container before the clip-path
is applied and so, it also gets clipped out. You can see this in the below snippet:
div {
display: inline-block;
height: 200px;
width: 200px;
border: 3px solid;
background: darkseagreen;
}
div + div {
-webkit-clip-path: polygon(50% 0%, 100% 100%, 100% 0%);
clip-path: polygon(50% 0%, 100% 100%, 100% 0%);
}
<div></div>
<div></div>
Custom Layout that rounds the corners of its content
The right way to create a ViewGroup
that clip its children is to do it in the dispatchDraw(Canvas)
method.
This is an example on how you can clip any children of a ViewGroup
with a circle:
private Path path = new Path();
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// compute the path
float halfWidth = w / 2f;
float halfHeight = h / 2f;
float centerX = halfWidth;
float centerY = halfHeight;
path.reset();
path.addCircle(centerX, centerY, Math.min(halfWidth, halfHeight), Path.Direction.CW);
path.close();
}
@Override
protected void dispatchDraw(Canvas canvas) {
int save = canvas.save();
canvas.clipPath(circlePath);
super.dispatchDraw(canvas);
canvas.restoreToCount(save);
}
the dispatchDraw
method is the one called to clip children. No need to setWillNotDraw(false)
if your layout just clip its children.
This image is obtained with the code above, I just extended Facebook ProfilePictureView
(which is a FrameLayout
including a square ImageView
with the facebook profile picture):
So to achieve a round border you do something like this:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// compute the path
path.reset();
rect.set(0, 0, w, h);
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
path.close();
}
@Override
protected void dispatchDraw(Canvas canvas) {
int save = canvas.save();
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(save);
}
You can actually create any complex path :)
Remember you can call clipPath multiple times with the "Op" operation you please to intersect multiple clipping in the way you like.
NOTE: I created the Path in the onSizeChanged
because doing so in the onDraw
is bad for performance.
NOTE2: clipping a Path is done without anti-aliasing :/ so if you want smooth borders you'll need to do it in some other way. I'm not aware of any way of making clipping use anti-aliasing right now.
UPDATE (Outline)
Since Android Lollipop (API 21) elevation and shadows can be applied to views. A new concept called Outline has been introduced. This is a path that tells the framework the shape of the view to be used to compute the shadow and other things (like ripple effects).
The default Outline
of the view is a rectangular of the size of the view but can be easily made an oval/circle or a rounded rectangular. To define a custom Outline
you have to use the method setOutlineProvider()
on the view, if it's a custom View you may want to set it in the constructor with your custom ViewOutlineProvider
defined as inner class of your custom View. You can define your own Outline
provider using a Path
of your choice, as long as it is a convex path (mathematical concept meaning a closed path with no recess and no holes, as an example neither a star shape nor a gear shape are convex).
You can also use the method setClipToOutline(true)
to make the Outline also clip (and I think this also works with anti-aliasing, can someone confirm/refute in comments?), but this is only supported for non-Path
Outline.
Good luck
How can I combine a circle in a polygon using clip-path and add a shadow
It is possible to 'cut holes' using the mask-image property and radial-gradients.
This snippet uses your code but replacing the clip-path with circle radial-gradient masks. Obviously you can change the percentages depending on hole-size required.
body {
background: cyan;
}
.ticket {
background-color: blue;
height: 100px;
width: 200px;
border-radius: 10px;
box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 15%);
--mask1: radial-gradient(circle at 0 50%, transparent 0, transparent 5%, black 5%, black 90%, transparent 90%, transparent);
--mask2: radial-gradient(circle at 100% 50%, transparent 0, transparent 5%, black 5%, black 90%, transparent 90%, transparent);
/* webkit needed for Chrome */
-webkit-mask-image: var(--mask1), var(--mask2);
mask-image: var(--mask1), var(--mask2);
}
<div class="ticket"></div>
Related Topics
Wrapping a Text Around a Circular Element
How to Overwrite CSS Variable with Its Own Value
Why Is a Pseudo-Class So Called
Center Overflowing Div Inside Smaller Div
How to Target CSS3 Columns Individually with Selectors
Css-Selector for Multiple Elements
How a CSS Pixel Size Is Calculated
Css: How to Position Element in Lower Right
How to Change Default Bootstrap Fluid Grid 12 Column Gutter Width
Margin-Top Percentage Does Not Change When Window Height Decreases
How to Add a Company Logo to Shinydashboard Header (Not Mainpanel or Mainheader)
How to Have Multiple Columns That Consume 100% Height Using Twitter Bootstrap
How to Compensate for Vertical Scrollbar When It Is Not Yet Present
CSS Fluid Layout: Margin-Top Based on Percentage Grows When Container Width Increases