This is the fifth day of my participation in Gwen Challenge

Adaptive ellipses

problem

As we all know, setting a border-radius of 100px to a square element with a width and height of 200px will make it a circle. We also know that if you specify any radius larger than 100px, you still get a circle.

When the sum of the radii of any two adjacent rounded corners exceeds the size of the border-box, the user agent must scale down the values used for each border radius until they do not overlap each other.

However, we often don’t want to specify a width and height for an element and want it to adapt to the content. So we want the following effect: if it has the same width and height, it appears as a circle; If the width and height are different, it appears as an ellipse.

The solution

Border-radius specifies the horizontal and vertical radius separately, separating the two values with a slash. So if we have an element with a size of 200px✖️100px, we can set the radius of its two corners to be half the width and half the height to create a precise ellipse. However, as soon as the element changes, you need to change the value of border-radius.

In fact, border-radius accepts not only length values, but also percentage values, which are resolved based on the size of the element. So to create an adaptive ellipse, just set both radius values to 50%. Since the values before and after the slash are the same, it can be simplified as:

/* The following code produces an adaptive ellipse */
border-radius:50%;  
Copy the code

Half elliptical

Border-radius includes each expanded attribute:

  • border-top-left-radius
  • border-top-right-radius
  • border-bottom-left-radius
  • border-bottom-right-radius

Thus, we can provide completely different horizontal and vertical radii for all four angles by specifying 1 or 4 values before the slash and another 1 or 4 values after the slash. Thus, we can achieve a semi-ellipse by:

/* When border-radius is 10px / 5px 20px, it is equivalent to 10px 10px 10px 10px 10px 10px / 5px 20px 5px 20px. * /
border-radius: 50% / 100% 100% 0 0;   /*下图一*/
border-radius: 100% 0 0 100% / 50%;   /*下图二*/
border-radius: 50% /  0 0 100% 100%;  /*下图三*/
border-radius: 0 100% 100% 0 / 50%;   /*下图四*/
Copy the code

A quarter ellipse

To create a quarter ellipse, one of the corners needs to have a horizontal and vertical radius of 100%, while the other three corners cannot be rounded. Since the radii of all four corners are the same horizontally and vertically, the slash syntax is not required.

border-radius: 100% 0 0 0;    /*下图一*/
border-radius: 0 0 0 100%;    /*下图二*/
border-radius: 0 0 100% 0;    /*下图三*/
border-radius: 0 100% 0 0;    /*下图四*/
Copy the code

Note: is it still usableborder-radiusTo generate other pieces of the ellipse (e.g. an eighth ellipse, a third ellipse)? I’m sorry,border-radiusProperty cannot generate these shapes.

Candy button

parallelogram

problem

A parallelogram is a superset of rectangles: its sides are parallel in pairs, but its angles are not always right angles.

We first stretch the rectangle with the skew() deformation property:

transform: skewX(-45deg);
Copy the code

The effect is as follows:

Not only did the rectangle get tilted, but its contents also got tilted, which was ugly and hard to read. Is there a way to tilt the shape of the container while keeping its contents the same?

Nested element scheme

You can apply another reverse skew() distortion to the content to offset the container distortion, but that means wrapping the content with an extra layer of HTML elements.

<a href="#yolo" class="button">
    <div>Click me</div>
</a>
<style>
    .button { transform: skewX(-45deg); }
    .button > div { transform: skewX(45deg); }
</style>
Copy the code

Pseudoelement scheme

Another way to think about it is to apply all the styles to the pseudo-elements and then denaturate them. But squares generated with fake elements are superimposed on top of the content, obscuring the content once you set a background to it. Therefore, you need to set the pseudo-element z-index:-1 to achieve this.

.button {
    position: relative;
/* Other text color, inner margins, etc... * /
}
.button::before {
    content: ' '; /* Create a rectangle with a false element */
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -1;
    background: lightseagreen;
    transform: skew(45deg);
}
Copy the code

The diamond pictures

problem

It is a common design method to cut the picture into diamond shape. Usually, it is not expected to be processed well in the image processing software. Such maintenance costs are too high, so it is necessary to process the code to make a normal picture displayed in the way of diamond shape.

A scheme based on deformation

Wrap the image in a div and apply the reverse rotate() style to it. Try it first:

<div class="picture">
    <img src="1.jpg" alt="..." />
</div>
.picture {
    width: 150px;
    transform: rotate(45deg);
    overflow: hidden;
}
.picture > img {
    max-width: 100%;
    transform: rotate(-45deg);
}
Copy the code

But the end result was to cut it into an octagon. Max-width: 100% 100% will be resolved to the.picture side length of the container. However, we want the width of the image to be equal to the diagonal of the container, not to the side length. So you need to use scale to enlarge the image. The two results are compared as follows:

.picture {
    width: 400px;
    transform: rotate(45deg);
    overflow: hidden;
}
.picture > img {
    max-width: 100%;
    transform: rotate(-45deg) scale(1.42);
}
Copy the code

Cutting path scheme

The above scheme mostly works, but it requires an extra layer of HTML tags and can be problematic if you’re dealing with a non-square image.

You can use the clip-path property, which can crop elements to any shape you want. You can specify a diamond using the polygon() function. In fact, it can specify any polygon using a series of comma separated coordinate points. You can also use percentages, which are resolved to the dimensions of the element itself.

Clip-path does not stop there. This property can even be involved in animation, as long as the animation is between the same shape function (polygon() in this case) and the same number of points. If we want the image to smoothly expand to full area over the mouse, just do this:

img {
    width: 150px;
    height: 150px;
    clip-path: polygon(50% 0.100% 50%.50% 100%.0 50%);
    transition: 1s clip-path;
}

img:hover {
    clip-path: polygon(0 0.100% 0.100% 100%.0 100%);
}
Copy the code

One last word

If this article is helpful to you, or inspired, help pay attention to it, your support is the biggest motivation I insist on writing, thank you for your support.