Using CSS Clip with Percentage

Using CSS Clip with percentage

Update (after 5+ years):

The CSS clip property is now deprecated. Consider using clip-path instead (allowing for a non-JS solution), which allows you to specify shapes with percentages. Example:

/* Bottom half of image */
clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0% 100%);

/* Top half of image */
clip-path: polygon(0 0, 100% 0, 100% 50%, 0 50%);

Further example to create a triangle using percentages:

clip-path: polygon(50% 0%, 0% 100%, 100% 100%);

Original:
CSS clip property does not currently support percentages:
http://www.w3.org/TR/CSS2/visufx.html#propdef-clip , latest http://www.w3.org/TR/2011/REC-CSS2-20110607/visufx.html#clipping

A solution to your problem could be to use Javascript to determine the size of the area you want to show, and then use that value when setting the clip property. Something as simple as this should do the trick:

var heightOfImageToDisplay = image.height / 2;

Migrating from clip to clip-path to use percent values

I would use mask for this

.box {
width: 40%;
height: 100px;
margin: 10px auto;
color: #000;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
position: relative;
}

.box::before, .box::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
box-shadow: inset 0 0 0 1px;
-webkit-mask:linear-gradient(#fff 0 0) no-repeat;
animation:
clipMe 2s linear infinite alternate,
pos 8s linear infinite;
}

.box::before {
animation-delay: -4s;
}

@keyframes clipMe {
0% {
-webkit-mask-size:100% 2px;
}
100% {
-webkit-mask-size:2px 100%;
}
}

@keyframes pos {
0%,24.9% {
-webkit-mask-position:top left;
}
25%,49.9% {
-webkit-mask-position:bottom left;
}
50%,74.9% {
-webkit-mask-position:bottom right;
}
75%,100% {
-webkit-mask-position:top right;
}
}
<div class="box"></div>

<div class="box" style="width:50%;height:150px;"></div>

Can we use percentage in clip css?

Instead of using the clip property, which is deprecated, you can use the clip-path property instead, and use a polygon (or even an SVG). For a polygon, you define it in x y pairs for the coordinate: 0 0 would be the top left, 100% 0 would be the top right, etc.

Take this example one for instance, it will clip the square divs to 65% width and 30% height.

div { margin: 10px; background: #0095ee; border: 10px solid #000; }
#a { width: 100px; height: 100px; } #b { width: 200px; height: 200px; }

div {
clip-path: polygon( 0 0, 65% 0, 65% 30%, 0 30% );
}
<div id="a"></div>
<div id="b"></div>

Transform CSS clip-path with mixed (fixed and percentage) values to SVG clip-path

With the help from Stack Overflow in Russian using SVG mask my solution is this

.container {  width: 200px;  height: 200px;}
svg { width: 100%; height: 100%;}
<div class="container">  <svg>    <defs>      <mask id="triangle-clip">        <rect x="0" y="0" width="100%" height="100%" fill="#fff" />        <path d="M0,20 v-20 h20 z" fill="#000" />      </mask>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" /> <stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" /> </linearGradient> </defs> <rect width="100%" height="100%" fill="url(#grad1)" mask="url(#triangle-clip)" /></svg></div>

How do I keep the aspect ratio of a percentage based clipping path?

One posible solution is this one:

.upper-poly {
position: absolute;
width: 80%;
height: 0%;
padding-bottom: 80%;
-webkit-clip-path: polygon(0 0, 50% 100%, 100% 0);
background: url(http://25.media.tumblr.com/fe6e34ef00254f2bd05451f525b02324/tumblr_mw8osqc77F1qdrz3yo3_500.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}

If the window aspect ratio is too wide, however, the triangle will be cut.

This works because vertical padding expressed as percentage is calculated on the parent width and not height.

Clipping CSS linear gradient based on width percentage

I used clip-path and padding-right. I didn't use pseudo or extra element.

body {
font-size: 30px;
width: 350px;
margin: 50px auto;
}

.progress-custom {
display: flex;
align-items: center;
margin-bottom: 0.5em;
}

.progress {
display: flex;
height: 1rem;
overflow: hidden;
font-size: 0.75rem;
background-color: #e9ecef;
border-radius: 0.25rem;
height: 3em;
font-size: 0.6em;
flex: 1;
position: relative;
}

.progress-bar {
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
color: #fff;
text-align: center;
white-space: nowrap;
transition: width 0.6s ease;
overflow: hidden;
background: linear-gradient(to right, gold, red);
padding-right:calc(100% - var(--width));
width: 100%;
height: 100%;
-webkit-clip-path: inset(0 calc(100% - var(--width)) 0 0);
clip-path: inset(0 calc(100% - var(--width)) 0 0);
}

.progress-custom .progress-value {
font-size: 0.8em;
padding: 0 0.5em;
}
<div class="progress-custom">
<div class="progress">
<div role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" class="progress-bar" style="--width: 70%;">
My Progress
</div>
</div>
<span class="progress-value"> 70%</span>
</div>
<div class="progress-custom">
<div class="progress">
<div role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" class="progress-bar" style="--width: 50%;">
My Progress
</div>
</div>
<span class="progress-value"> 50%</span>
</div>
<div class="progress-custom">
<div class="progress">
<div role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" class="progress-bar" style="--width: 20%;">
My Progress
</div>
</div>
<span class="progress-value"> 20%</span>
</div>

svg clipPath using absolute points instead of percentages

You may try to use clipPathUnits="objectBoundingBox" for the clipPath.

This indicates that all coordinates inside the <clipPath> element are relative to the bounding box of the element the clipping path is applied to. It means that the origin of the coordinate system is the top left corner of the object bounding box and the width and height of the object bounding box are considered to have a length of 1 unit value.

Plrase read about clipPathUnits

Please observe that the polygons have transform="scale(.01)" i.e 1/100. Now the values are percentages.

.clip-svg {
clip-path: url(#myClip);
}

img{width:95vw;}
<img class="clip-svg" src="https://assets.codepen.io/222579/castell.jpg" />

<svg viewBox="0 0 100 100" width="0" height="0">

<clipPath id="myClip" clipPathUnits="objectBoundingBox">
<polygon transform="scale(.01)" points="89,0 100,50 89,100 71,100 83,50 69,0" />
<polygon transform="scale(.01)" points="53,0 75,50 59,100 48,100 64,50 41,0" />
</clipPath>
</svg>


Related Topics



Leave a reply



Submit