Abaloada shape with CSS how to do? How to make a Shape in this kind of aredondado format?

Asked

Viewed 232 times

7

I would like to make an element half round, it is not an ellipse, nor a circle, nor an element with border-radius. It’s a kind of rounded shape as you can see in the image below and I couldn’t do it with CSS.

inserir a descrição da imagem aqui

I tried to arrive in this muffled shape, but I could not, it still gets a straight part on each side. I would like each side to be curved as well as in this frame of reference.

Follows my code.

html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background-color: rgb(231, 247, 255);
}
.box {
    width: 155px;
    height: 150px;
    background-image: linear-gradient(red, blue);
    border-radius: 45%;
    margin: 1rem auto;
}
<div class="box"></div>

OBS: I know with SVG I can, but my intention is that it is only with CSS

2 answers

6


There is the CSS property clip-path which you can use to cut unwanted parts from the background of the element.

This article from CSS Tricks has some cool examples to understand how property works.

To define a Shape complex you can:

  • Use the path() that takes as parameter a string containing a path in the same format as the SVG path.

    clip-path: path("M10 10 H 90 V 90 H 10 L 10 10");
    
  • Use a Clippath SVG and refer to the CSS.

    clip-path: url("#meu-clip");
    

Below is the path of your vector image that I will use in the examples:

m59.533456,149.455558c-16.519209,-1.510568 -33.831918,-7.984429 -41.622636,-15.609198c-24.814882,-24.169081 -23.227884,-99.913255 2.452634,-119.694497c11.686078,-8.991474 31.018602,-13.810903 55.256394,-13.810903c19.548933,0 32.605601,2.445681 44.796633,8.344088c15.437165,7.480906 23.30002,20.140901 27.988878,45.101232c1.731271,9.423064 1.731271,33.37635 -0.072136,43.302937c-1.514862,8.559883 -5.338085,20.50056 -8.512082,26.54283c-3.390405,6.401929 -11.181124,13.882835 -18.25048,17.479425c-12.118896,6.258066 -26.257608,8.919542 -46.239359,8.703746c-7.141492,-0.071932 -14.210848,-0.215795 -15.797846,-0.359659z

Examples

path()

body {
  background-color: #eedddd;
  display: flex;
  justify-content: center;
  padding: 15px;
}

.quadrado {
  display: inline-block;
  width: 150px;
  height: 150px;
  background: linear-gradient(#3ce092, #3b91b7);
  clip-path: path("m59.533456,149.455558c-16.519209,-1.510568 -33.831918,-7.984429 -41.622636,-15.609198c-24.814882,-24.169081 -23.227884,-99.913255 2.452634,-119.694497c11.686078,-8.991474 31.018602,-13.810903 55.256394,-13.810903c19.548933,0 32.605601,2.445681 44.796633,8.344088c15.437165,7.480906 23.30002,20.140901 27.988878,45.101232c1.731271,9.423064 1.731271,33.37635 -0.072136,43.302937c-1.514862,8.559883 -5.338085,20.50056 -8.512082,26.54283c-3.390405,6.401929 -11.181124,13.882835 -18.25048,17.479425c-12.118896,6.258066 -26.257608,8.919542 -46.239359,8.703746c-7.141492,-0.071932 -14.210848,-0.215795 -15.797846,-0.359659z");
}
<div class="quadrado"></div>

It is worth remembering that the clip-path is experimental, so the support is very low.

The above example works on Firefox 64 by enabling flag:

layout.css.clip-path-path.enabled

SVG

body {
  background-color: #eedddd;
  display: flex;
  justify-content: center;
  padding: 15px;
}

.quadrado {
  display: inline-block;
  width: 150px;
  height: 150px;
  background: linear-gradient(#3ce092, #3b91b7);
  clip-path: url("#tela-tv-tubo");
}
<div class="quadrado"></div>

<svg width="0" height="0">
  <defs>
    <clipPath id="tela-tv-tubo">
      <path d="m59.533456,149.455558c-16.519209,-1.510568 -33.831918,-7.984429 -41.622636,-15.609198c-24.814882,-24.169081 -23.227884,-99.913255 2.452634,-119.694497c11.686078,-8.991474 31.018602,-13.810903 55.256394,-13.810903c19.548933,0 32.605601,2.445681 44.796633,8.344088c15.437165,7.480906 23.30002,20.140901 27.988878,45.101232c1.731271,9.423064 1.731271,33.37635 -0.072136,43.302937c-1.514862,8.559883 -5.338085,20.50056 -8.512082,26.54283c-3.390405,6.401929 -11.181124,13.882835 -18.25048,17.479425c-12.118896,6.258066 -26.257608,8.919542 -46.239359,8.703746c-7.141492,-0.071932 -14.210848,-0.215795 -15.797846,-0.359659z"/>
    </clipPath>
  </defs>
</svg>

  • The SVG I know could solve the case, but my intention is still to achieve with CSS ... if possible...

  • 1

    If I can convert the <path> for css poligon I can take it off.. update as soon as I figure out a way

  • I arranged another way.... and you won’t believe :D http://prntscr.com/lx7q1u loved publishing!

5

Option 1

With only a div and its pseudo-elements ::after and ::before it is possible to get a result very faithful to the reference image.

The idea is to have a div main as container. Then in the element ::before we created a linear-gradiente that will be our background color. And then we will put a border-radius in that ::before only to fine-tune the curvature of the vertices.

The second step is with the ::after. Here is the main point, because the ::after will receive TWO radial-gradiente, one vertical and one horizontal, these gradients start from the color transarente for the background color that in the case is white. Like the ::after is over the ::before it will work like a mask.

To help you understand I leave this diagram. inserir a descrição da imagem aqui

Here the border-radius was applied in the ::before to fine-tune the corners. inserir a descrição da imagem aqui

This is the final result, still giving a margin for adjustments :D

inserir a descrição da imagem aqui

Code referring to image above. Leave comments in the code where to make the adjustments.

html, body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0;
}
body {
    display: flex;
    align-items: center;
    justify-content: center;
}
.box {
    height: 21.5vw;
    width: 22vw;
    position: relative;
}
.box::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background-image:  linear-gradient(to top, #2196F3 20%,#3CDE92 80%);
    background-position: center;
    background-size: 170% 230%;
    background-repeat: no-repeat;
/* controla o ajuste fino nos cantos */
    border-radius:46%;
}
.box::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
/* cor da mascara deve ser igual a cor do fundo */
    background-image: radial-gradient( transparent 38%, rgba(255, 255, 255, 1) 39%), radial-gradient( transparent 38%, rgba(255, 255, 255, 1) 39%);
    background-position: center;
    background-size: 170% 230%, 230% 170%;
}
<div class="box"></div>

OBS: The limitation is that the color of the mask made with the radial-gradiente of ::after shall be the same background colour, shall be a solid colour preferably...


Option 2

This I think is not yet the perfect model, but is an option with the factor crossbrowser much better. It is made with 2 pseudo-elements ::after and ::before in a div and linear-gradient. I also needed to use transform to try to get the closest to the reference image. Also need to put this div within a container, just to make a fine-tuning transform: scaleY(.95) to try to stay more faithful to the base image.

inserir a descrição da imagem aqui

I made the treated model next to a complete circle with border-radius: 50% and another with border-radius: 45%, the difference is subtle, but I thought it was worth leaving the answer there.

Follow the model code above

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
body {
  background-color: #ddd;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}
.container {
  position: absolute;
  width: 100px;
  height: 100px;
  transform: scaleY(.95);
}
.box {
  position: absolute;
  width: 100px;
  height: 100px;
  transform: rotate(-45deg);
  border-radius: 41%;
  background: linear-gradient(225deg,#3CDE92, #3B92B7);
}
.box::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: linear-gradient(to left,#3CDE92, #3B92B7);
  transform: scaleX(1.1) rotate(-45deg);
}
.box::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: linear-gradient(to left,#3CDE92, #3B92B7);
  transform: scaleY(1.1) rotate(-45deg);
}
.controle {
  position: absolute;
  width: 105px;
  height: 105px;
  border-radius: 45%;
  background: linear-gradient(to bottom,#3CDE92, #3B92B7);
  transform: translateX(120px);
}
.bola {
  position: absolute;
  width: 105px;
  height: 105px;
  border-radius: 50%;
  background: linear-gradient(to bottom,#3CDE92, #3B92B7);
  transform: translateX(-120px);
}
<div class="bola"></div>

<div class="container">
  <div class="box"></div>
</div>

<div class="controle"></div>

  • Boy, if you pulled with that option 1!

  • @fernandosavio here the stuff is Oko!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.