Draw double curved item with beveled edges

前端 未结 4 1580
半阙折子戏
半阙折子戏 2021-01-14 01:16

I\'m creating a website, with a header / menu on top. In the middle, there is a logo. To accentuate this, I\'ve absolute positioned an ellips below the logo: So underneath,

相关标签:
4条回答
  • 2021-01-14 01:27

    SVG would be the way to go for such things but for a CSS solution I would probably use multiple background with linear/radial-gradient BUT the drawback is that it can be difficult to calculate the different values and make the whole shape responsive.

    Here is an example that can help you get some idea:

    body {
      background:grey;
    }
    
    .header {
      border: 5px solid red;
      border-top: none;
      height: 100px;
      width: 600px;
      background: 
      radial-gradient(ellipse at -7px 26px, transparent 50%, red 50%, red calc(50% + 11px), white 0%) 101px -3px/7% 19% no-repeat, 
      radial-gradient(ellipse at 60px 26px, transparent 50%, red 50%, red calc(50% + 11px), white 0%) 454px -4px/7% 19% no-repeat, 
      radial-gradient(ellipse at top, white 20%, red 20%, red calc(21% + 2px), transparent 0%) 50% 0/200% 200% no-repeat,
      linear-gradient(red 50%,transparent 0%) 0 0/100% 10px no-repeat, 
      linear-gradient(to right, gray, blue);
    }
    .header-tr {
      border: 5px solid red;
      margin-top:20px;
      border-top: none;
      height: 100px;
      width: 600px;
      background: 
      radial-gradient(ellipse at -7px 26px, transparent 50%, red 50%, red calc(50% + 11px), white 0%) 101px -3px/7% 19% no-repeat, 
      radial-gradient(ellipse at 60px 26px, transparent 50%, red 50%, red calc(50% + 11px), white 0%) 454px -4px/7% 19% no-repeat, 
      radial-gradient(ellipse at top, white 20%, red 20%, red calc(21% + 2px), transparent 0%) 50% 0/200% 200% no-repeat,
      linear-gradient(red 50%,transparent 0%) 0 0/110px 10px no-repeat,
      linear-gradient(red 50%,transparent 0%) 100% 0/110px 10px no-repeat;
    }
    <div class="header">
    
    </div>
    
    <div class="header-tr">
    
    </div>

    And if you are open to use multiple element you can rely on pseudo element and some border-radius but you have also to manage a lot of element:

    body {
      background: gray;
    }
    
    .header {
      margin-top: 30px;
      border: 5px solid red;
      border-top: none;
      height: 100px;
      position: relative;
      overflow: auto;
    }
    
    .top {
      position: absolute;
      top: -40px;
      right: 80px;
      left: 80px;
      height: 80px;
      border: 5px solid red;
      border-top: none;
      border-radius: 0 0 50% 50%;
      background: #fff;
    }
    
    .top:before {
      content: "";
      position: absolute;
      top: 23px;
      right: calc(100% - 11px);
      left: -80px;
      border-top: 18px solid #fff;
      border-radius: 0 50% 0 0;
      border-bottom: 0;
      border-left: 0;
      height: 52px;
      z-index: 0;
    }
    
    .top:after {
      content: "";
      position: absolute;
      top: 23px;
      left: calc(100% - 11px);
      right: -80px;
      border-top: 18px solid #fff;
      border-radius: 50% 0 0 0;
      border-bottom: 0;
      border-right: 0;
      height: 52px;
      z-index: 0;
    }
    
    .header:before {
      content: "";
      position: absolute;
      top: 0;
      right: calc(100% - 88px);
      left: 0;
      border-top: 5px solid red;
      border-radius: 0 50% 0 0;
      border-bottom: 0;
      border-left: 0;
      height: 25px;
      z-index: 99;
    }
    
    .header:after {
      content: "";
      position: absolute;
      top: 0;
      left: calc(100% - 88px);
      right: 0;
      border-top: 5px solid red;
      border-radius: 50% 0 0 0;
      border-bottom: 0;
      border-right: 0;
      height: 25px;
      z-index: 99;
    }
    <div class="header">
      <div class="top"></div>
    </div>

    And here is an SVG solution:

    <svg
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 75 50'
      width='600' height='300'
      fill='transparent'>
      <path d='M0 24 L64 24 L64 2 L58 2 C36 2 46 10 32 10 C18 10 26 2 4 2 L0 2 Z' stroke="red" stroke-width="1" />
    </svg>

    0 讨论(0)
  • 2021-01-14 01:34

    Almost there ... it could get you in the way.

    I used ::before and ::after on the header to add two curve.

    Play a little with the values of the radius to get what you want.

    The ellips has a fixed width, so this is as responsive as possible. When resizing the screen, the corners won't break but the ellip's size won't change.

    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }
    
    body {
      background: linear-gradient(to right, #d2e1f1, #86acd0);
    }
    
    header {
      height: 100px;
      background: white;
      position: relative;
    }
    header::before, header::after {
      content: "";
      display: block;
      width: calc(50% - 80px);
      position: absolute;
      top: 95px;
      height: 80px;
      border: 6px solid #dadbe0;
      border-right-color: transparent;
      border-left-color: transparent;
      border-bottom: 0;
      z-index: 3;
    }
    header::before {
      left: 0px;
      border-radius: 0px 140px 0px 0px/0px 60px 0px 0px;
    }
    header::after {
      right: 0px;
      border-radius: 140px 0px 0px 0px/60px 0px 0px 0px;
    }
    
    .ellips {
      background: white;
      height: 120px;
      width: 300px;
      position: absolute;
      bottom: -40px;
      z-index: -1;
      border-radius: 0px 0px 90% 90%/0px 0px 90px 90px;
      left: 50%;
      transform: translate(-50%);
      border: 6px solid #dadbe0;
    }
    
    .masks {
      background: white;
      height: 9px;
      width: 330px;
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%);
      z-index: 2;
      border-radius: 0px 0px 90% 90%/0px 0px 90px 90px;
      bottom: -8px;
    }
    <header>
      <div class="ellips">
      </div>
      <div class="masks"></div>
    </header>

    0 讨论(0)
  • I created 2 SVG examples so you can choose where to apply the background

    Codepen demo


    The outer container of each SVG element keeps a specific aspect ratio so the whole element can be responsive (but, of course, you can also specify a fixed width or height).

    The basic idea is to create a path that overflows the size of the SVG element, so you can define a closed shape on the top area or on the bottom area, in order to fill it with a colour (if you enlarged the viewbox e.g. to -10 -10 610 130 you could see how the path is actually defined).

    The applied background is a gradient but you can also specify a single color-stop (white, in your specific scenario). The background on the body element shows the transparent parts of the SVG.

    Fine tuning and adjustment of curves, viewbox, colours is left to the reader.

    For any change to the shape you can read the path documentation on MDN

    Markup

    <div class="doublecurve">
      <svg viewBox="0 0 600 120" xmlns="http://www.w3.org/2000/svg">
    
        <defs>
          <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%"   stop-color="#d8e5f1" />
            <stop offset="100%" stop-color="#91b4d3" />
          </linearGradient>
        </defs>
    
        <path class="concave" fill="url(#gradient)" d="M-2 2 
                L75 2 A75 75 0 0 1 110 20 C200 100 400 100 480 20
                A75 75 0 0 1 525 2 L602 2 L602 122 L-2 122 z"/>
      </svg>
    </div>
    
    
    
    <div class="doublecurve">
      <svg viewBox="0 0 600 120" xmlns="http://www.w3.org/2000/svg">
    
        <defs>
          <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%"   stop-color="#d8e5f1"/>
            <stop offset="100%" stop-color="#91b4d3"/>
          </linearGradient>
        </defs>
    
        <path class="concave" fill="url(#gradient)" d="M-2 2 
                L75 2 A75 75 0 0 1 110 20 C200 100 400 100 480 20
                A75 75 0 0 1 525 2 L602 2 L602 -2 L-2-2"/>
      </svg>
    </div>
    

    CSS

    .doublecurve {
      width: 100%;
      height: 0;
      margin: 20px 0;
      border: 1px dashed #bc9;
      padding-bottom: 20%;
      position: relative; }
    
    .doublecurve svg { 
      position: absolute;
      width: 100%; height: 100%;}
    
    .doublecurve path.concave { 
      stroke: #d0d0d0; 
      stroke-width: 4px;}
    

    Final Result

    0 讨论(0)
  • 2021-01-14 01:48

    Here is an inline-SVG solution with a quadratic bezier curve.
    The svg image has 500x50 pixels dimensions and is absolute positioned into the header.

    .your-header {
      border-top: 2px solid #dfe0e4;
      position: relative;
    
      /* These two are just for demo */
      background-color: lightblue;
      height: 75px;
    }
    
    svg.ellipse {
      height: 50px;
      width: 500px;
      /* Centers the svg horizontal */
      left: 50%;
      margin-left: -250px;
      position: absolute;
      /* 2px up due to the parents border */
      top: -2px;
    }
    
    svg.ellipse > .border-clear{
      /* A white line to cover up the parents border */
      stroke: white;
      stroke-width: 3px;
    }
    
    svg.ellipse>.wave {
      stroke: #dfe0e4;
      stroke-width: 2px;
      fill: white;
    }
    <div class="your-header">
      <svg class="ellipse">
        <path d="M0 0 H499" class="border-clear" />
        <path d="M0 1 Q 62.5 1, 125 26 T 250 49 T 375 26 T 500 1" class="wave"/>
      </svg>
    </div>

    0 讨论(0)
提交回复
热议问题