CSS to draw various shapes

Adaptive Ellipse


1. Adaptive Ellipse


Implementation is through the border-radius property; border-radius can specify the horizontal and vertical radii separately. Separate the two values ​​with /. And the value of this property can accept not only the length value, but also the percentage value. Percentage values ​​are parsed based on the size of the element, width is the resolution of the horizontal radius, and height is the resolution of the vertical radius.


So you can set the values ​​of both radii to 50%;


border-radius: 50% / 50%; 
/* If the values ​​are both 50%, it can be simplified to border-radius: 50%; */
The final effect:






2. The value of


border-radius can be set separately, separated by spaces, and even completely different horizontal and vertical radii can be provided for the four corners.


The rendering order of the four values ​​of border-radius starts from the upper left corner and renders clockwise;
when only 3 values ​​are given, the fourth value is equal to the second;
when two values ​​are given, the third value is equal to the first value, and the fourth value is equal to the second value.


So the implementation method of the semi-ellipse is:


border-radius: 50% / 100% 100% 0 0; 


/*
 * will be parsed as the following
    border-top-left-radius: 50% 100%;
    border-top-right- radius: 50% 100%;
    border-bottom-right-radius: 50% 0px;
    border-bottom-left-radius: 50% 0px;
*/
Final effect:






the same way to generate a quarter ellipse:


/* If you cannot set rounded corners Set to 0 */
border-radius: 100% 0 0 0;
Final effect:






realization of parallelogram


When generating a parallelogram, directly use transform: skew(-45deg); deformation on the current div, which will cause the content inside the div Deformation will also occur, as follows: The






general solution is to use the pseudo-element method, which is to apply all styles to the pseudo-element and deform the pseudo-element. Since the content is not in the pseudo-element, the content will not be affected by the pseudo-element. influence. The specific implementation is as follows:


<div class="parallelogram">
    click
</div>
.parallelogram {
    text-align: center;
    position: relative;
}


.parallelogram::before {
    transform: skew(-45deg);
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: -1;
    content: ' ';
    background: #fb3;
}
The resulting effect is as follows:






This trick is not only useful for skew() deformation, but also As with any other transform style, it can be used when you want to transform any element without changing its content.


The generation of diamond-shaped pictures


In CSS, some requirements are to cut the picture into a diamond shape. Using CSS can solve this problem very well, because there is no need to cut the picture into a diamond shape in advance and affect the later maintenance.


Deformation-based solution


Directly use a parallelogram-like rotation and set max-width: 100% for img, which will cause the image to be cropped into an octagon. Because 100% will be parsed into the side length of the div. So the solution to this problem is to make the width of the image equal to the length of the diagonal of the div container. A better way is to use scale to enlarge the image by 2 times the root sign (about 1.42 times). The specific implementation code is as follows:


< div class="picture">
    <img src="cat.jpg" />
</div>
.picture {
    width: 400px;
    height: 400px;
    transform: rotate(45deg);
    overflow: hidden;
}


.picture1 > img {
    max-width: 100%;
    height: 400px;
    transform: rotate(-45deg) scale(1.42);
} The
effect is as follows:






The difference between scale and width enlargement: the scaled image of scale is Its center point is scaled (without specifying transform-origin), when the image is enlarged by the width property, it will only be scaled with the origin of its upper left corner, and then the position of the image will be adjusted with an additional negative margin .


The above method of clipping path scheme also needs to put a layer of extra html tags in front of it, use the attribute clip-path, which is originally an attribute of svg, and use the polygon() function of this polygon, the value of the percentage used will be parsed as an element own size.


img {
    clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
The clip-path property can also participate in animation, as long as the animation is performed between the same shape function , and the number of points is the same, for example, we want the mouse hover to smoothly expand to the completed area, just like this:


.picture {
    clip-path: polygon(50% 0, 100% 50%, 50% 100 %, 0 50%);
    transition: 1s clip-path;
}
.picture:hover {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
The realization of the foot cutting effect The


radial gradient method To


achieve the effect of a corner being cut off, you can Use a gradient, which accepts an angle as a direction and allows the text to overflow beyond the chamfered area (because it's just the background pattern), implemented like this:


div {
  background: #58a;
  background: linear-gradient(-45deg, transparent 15px, #58a 0);
} The
effect is as follows:






two ways to cut corners:


div {
    width: 200px;
    height: 100px;
    background: #58a;
    background: linear-gradient(-45deg, transparent 15px, #58a 0) 
                right, linear-gradient(45deg, transparent 15px, #65a 
                 0) left;
    background-size: 50% 100%;
    background-repeat: no-repeat;
} The
effect is as follows:




The implementation of the same four corners:


div {
    width: 200px;
    height: 100px;
    background: #58a;
    background: linear-gradient(135deg, transparent 15px, #58a 0) top 
left, linear-gradient(-135deg, transparent 15px, #58a 0) top right, linear-gradient(-45deg, transparent 15px, #58a 0) bottom right, linear-gradient(45deg, transparent 15px, #58a 0) bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
} The
effect is as follows:






the above code is poorly maintained, and needs to be modified in many places when changing the corners and colors, so we can Use scss mixin to write:


@mixin beveled-corners($bg, $tl:0, $tr:$tl, $br:$tl, $bl:$tr) {
    background: $bg;
    background:
    linear-gradient(135deg, transparent $tl, $bg 0) top left,
    linear-gradient(225deg, transparent $tr, $bg 0) top right,
    linear-gradient(-45deg, transparent $br, $bg 0 ) bottom right,
    linear-gradient(45deg, transparent $bl, $bg 0) bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}
When calling:


@include beveled-corners(#58a , 15px, 5px);
the final result is a 15px chamfer in the upper left and lower right corners, and a 5px chamfer in the upper right and lower left corners. The above minxin sets the initial value. When the incoming value is less than four values, it is the same as the border-radius assignment.


In the same way we can also create arc chamfers, at least change to radial gradient


div {
    width: 200px;
    height: 100px;
    background: #58a;
    background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left, radial-gradient(circle at top right, transparent 15px, #58a 0) top right, radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right, radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
} The
effect is as follows




: By combining SVG and border-image,


SVG can achieve perfect scaling that is completely independent of size. When the text overflows, it will play the role of a normal border, making the text wrap. The specific implementation is as follows:


div {
  width: 200px;
  height: 100px;
  border: 15px solid transparent;
  border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="% 2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');
} The
effect is as follows:






Solve the middle The filling of the background color can add a background color to the div block with the same background color as the border:


div {
    width: 200px;
    height: 100px;
    border: 15px solid transparent;
    border-image: 1 url(data:image/svg+xml,\ <svg xmlns="http://www.w3.org/2000/svg" width="3" heigh="3" fill="%2358a">\<polygon points="0,1 1,0 2, 0 3,1 3,2 2,3 1,3 0,2"/>\</svg>);
    background: #58a;
    background-clip: padding-box;
}
Clipping Path Schemes The most amazing thing about CSS clipping paths is that we can use both percentage values ​​(which are converted from the element's own width and height as a base degree) and absolute length values, providing tremendous flexibility.


If you use a clipping path to cut an element with a 20px bevel, the specific code is as follows:


background: #58a;
clip-path: polygon( 20px 0, calc(100% - 20px) 0, 100% 20px, 100 % calc(100% - 20px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 20px), 0 20px);
The biggest advantage of this method is that you can use any type of background, even Replacement elements (such as images) can be cropped
, and animation effects are supported.


Disadvantage: When the padding is not wide enough, it cuts off the text.


The realization of the trapezoid label page The realization of the


trapezoid can be done through


div {
    position: relative;
    display: inline-block;
    padding: .5em 1em .35em;
    color: white;
}


div::before {
    content: '';
    position: absolute;
    top : 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: -1;
    background: #58a;
    transform: scaleY(1.3) perspective(.5em) rotateX(5deg);
    transform-origin: bottom;
} The
effect is as follows:






The transform effect will make the element rotate in space with its own center line as the axis , which makes its size difficult to control, the solution is to set transform-origin:bottom; to fix its bottom edge when it rotates in 3D space. While fixing the bottom edge, the shrinkage in height becomes more noticeable. To solve this problem, you can change its size through the transform property ( scaleY() ).


The same method can achieve the following tab layout: the






specific code is as follows:


nav > a {
    position: relative;
    display: inline-block;
    padding: .3em 1em 0;
}
nav > a::before {
    content: '';
    position : absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -1;
    background: #ccc;
    background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,0));
    border: 1px solid rgba(0,0,0,.4 );
    border-bottom: none;
    border-radius: .5em .5em 0 0;
    box-shadow: 0 .15em white inset;
    transform: perspective(.5em) rotateX(5deg); transform
    -origin: bottom ; Change the transform-origin to bottom left or bottom right, and you can immediately get a left-tilted or right-tilted tab. The disadvantage of this method is that the angle of the hypotenuse depends on the width of the element. However, for multiple elements that don't vary much in width (such as navigation menus), this approach works well. The idea is to designate the left and right parts of the circle as the above two colors, and then cover them with pseudo elements, and determine how large the sector is exposed by rotating. The specific code is as follows: .pie {     width: 100px;     height: 100px;     border-radius: 50%;     background: yellowgreen;


















    background-image: linear-gradient(to right, transparent 50%, #655 0);


.pie::before {
    content: '';
    display: block;
    margin-left: 50%;
    height: 100%;
    border-radius : 0 100% 100% 0 / 50%;
    background-color: inherit;
    transform-origin: left;
}
The effect is as follows:






This method also supports animation, you can use CSS animation to achieve a pie chart changing from 0 to 100% animation for a cool progress indicator:


@keyframes spin {
    to { transform: rotate(.5turn); }
}
@keyframes bg {
    50% { background: #655; }
}
.pie::before {
    content: '';
    display: block;
    margin-left: 50%;
    height: 100%;
    border-radius: 0 100% 100% 0 / 50%;
    background-color: inherit;
    transform-origin: left;
    animation: spin 3s linear infinite, bg 6s step-end
infinite
; The ratio of the static pie chart method can be achieved through the animation above. It is necessary to set the animation to be in a paused state, and then set a negative animation delay to jump directly to any time point in the animation. The final implementation code is as follows:


<div class="pie" style="animation-delay: -20s">
    <span>20</span>
</div>
<div class="pie" style="animation-delay: -60s">
    <span>60 </span>
</div>
.pie{
    position: relative;
    width: 100px;
    height: 100px;
    line-height: 100px;
    border-radius: 50%;
    background: yellowgreen;
    background-image: linear-gradient(to right, transparent 50%, #655 0);
    color: #000;
    text-align: center;
}


@keyframes spin {
    to { transform: rotate(.5turn); }
}
@keyframes bg {
    50% { background: #655; }
}


.pie::before {
    content: '';
    position: absolute;
    top: 0; left: 50%;
    width: 50%; height: 100%;
    border-radius: 0 100% 100% 0 / 50%;
    background-color: inherit;
    transform-origin: left;
    animation: spin 50s linear infinite, bg 100s step-end infinite;
    animation-play-state: paused;
    animation-delay: inherit;
}
.pie span {
    position: relative;
    z-index: 10;
} The
effect is as follows:






Solution with SVG


<svg viewBox="0 0 32 32">
    <circle r="16" cx=" 16" cy="16" />
</svg>
svg {
    width: 100px; 
    height: 100px;
    transform: rotate(-90deg);
    background: yellowgreen;
    border-radius: 50%;
}
circle {
    fill: yellowgreen;
    stroke : #655;
    stroke-width: 32;
    stroke-dasharray: 38 100; /* get a sector with a ratio of 38%*/
}
By making the perimeter of the pie chart infinitely close to 100, you can directly specify the percentage value of the ratio as the length of the strokedasharray without doing any calculations. Since the perimeter is 2πr, the radius is 100/22π ≈ 15.915, which is rounded up to 16. Specify its dimensions in the SVG's viewBox property, instead of using the width and height properties, so that it can automatically adapt to the size of the container.


What's great about SVG? It's very easy to add a third color, and you can use inline styles to specify the color.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325941133&siteId=291194637