Shape resembling a compass pointer or inner part of a Safari logo

前端 未结 1 1565
情深已故
情深已故 2020-12-30 12:28

I am trying to make the below shape using only CSS. I know that achieving this shape using an image or SVG would be a lot easier but I am trying to achieve it with CSS for a

相关标签:
1条回答
  • 2020-12-30 12:41

    For a needle resting on its tip

    Yes, it is possible to create that shape using only CSS. You have to rotate the shape along both the Y-axis and the Z-axis to achieve it.

    Rotating it along the Z-axis by 45 degrees will produce a diamond shape (as indicated in the question) and rotating it along the Y-axis by close to (but less than) 90 degrees will make only a part of the shape visible from the front and thereby would give it the appearance of having shorter diagonal lines (resembling a compass pointer).

    Additionally adding a linear-gradient for the background and a inset box-shadow will help to achieve a shape that is a lot closer to the shape shown in question.

    body {
      background: #333;
      font-family: Calibri;
      font-size: 18px;
    }
    div {
      height: 200px;
      width: 150px;
      display: inline-block;
      vertical-align: middle;
      color: white;
      padding-top: 40px;
    }
    .separator {
      background: #555;
      top: 40px;
      padding-top: 0px;
      height: 160px;
      width: 160px;
      background-image: linear-gradient(-45deg, #555 0%, #555 40%, #444 50%, #333 97%);
      box-shadow: inset 6px 6px 22px 8px #272727;
      transform: rotateY(87deg) rotate(45deg);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <div>
      Some lengthy paragraph content which wraps around when it exceeds the width
    </div>
    <div class='separator'></div>
    <div>
      Some lengthy paragraph content which wraps around when it exceeds the width
    </div>

    enter image description here


    For a needle resting on its base

    For a needle that is resting on its base, the rotation should be along the X-axis and Z-axis instead of along Y-axis and Z-axis for the needle resting on its tip. Below is a sample snippet.

    body {
      background: #AAA;
      font-family: Calibri;
      font-size: 18px;
    }
    div {
      height: 200px;
      width: 150px;
      display: inline-block;
      vertical-align: middle;
      color: white;
      padding-top: 40px;
      margin: 40px;
    }
    .separator {
      background: #555;
      top: 40px;
      padding-top: 0px;
      height: 160px;
      width: 160px;
      background-image: linear-gradient(-45deg, #555 0%, #555 40%, #444 50%, #333 97%);
      box-shadow: inset 6px 6px 22px 8px #272727;
      transform: rotateX(87deg) rotate(45deg);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <div class='separator'></div>


    Compass Pointer created using above method:

    Here is a sample compass pointer (inspired in part by the Safari logo) created purely using CSS. The pointer or the needle inside is created using the method explained above.

    .container {
      position: relative;
      height: 152px;
      width: 152px;
      padding: 10px;
      border-radius: 50%;
      background: radial-gradient(circle at 50% 50%, white 58%, #999 70%, #EEE 80%);
      border: 1px solid #AAA;
    }
    .dial {
      height: 150px;
      width: 150px;
      border-radius: 50%;
      background: linear-gradient(#1ad4fd, #1d65f0 100%);
      border: 1px solid #999;
      position: relative;
      animation: rotatedial 2s 6 alternate forwards;
    }
    .dial:after {
      content: '';
      position: absolute;
      top: 25px;
      left: 25px;
      height: 100px;
      width: 100px;
      background-image: linear-gradient(-45deg, white 0%, white 47%, red 50%);
      box-shadow: inset 0px 6px 22px 0px #CCC, inset -6px -6px 22px 0px #AAA;
      transform: rotateY(85deg) rotate(45deg);
    }
    .dial:before {
      content: '';
      position: absolute;
      top: 72px;
      left: 70px;
      height: 8px;
      width: 8px;
      background: radial-gradient(circle at 50% 50%, white 30%, grey 100%);
      border: 1px solid #999;
      border-radius: 50%;
      z-index: 2;
    }
    .hands,
    .hands-small {
      position: absolute;
      height: 150px;
      width: 150px;
      top: 11.25px;
      left: 11px;
      z-index: 0;
    }
    .hands:before,
    .hands:after,
    .hands .hand:before,
    .hands .hand:after {
      content: '';
      position: absolute;
      top: 0;
      left: 74.5px;
      width: 1px;
      height: 12px;
      background: #EEE;
      border-radius: 4px;
      box-shadow: 0px 138px #EEE;
      transform-origin: 50% 75px;
    }
    .hands-small:before,
    .hands-small:after,
    .hands-small .hand-small:before,
    .hands-small .hand-small:after {
      content: '';
      position: absolute;
      top: 0;
      left: 74.5px;
      width: 1px;
      height: 7px;
      background: #EEE;
      border-radius: 4px;
      box-shadow: 0px 143px #EEE;
      transform-origin: 50% 75px;
    }
    .hands:before {
      transform: rotate(-45deg);
    }
    .hands:after {
      transform: rotate(0deg);
    }
    .hand:before {
      transform: rotate(45deg);
    }
    .hand:after {
      transform: rotate(90deg);
    }
    .hands-small:before {
      transform: rotate(-22.5deg);
    }
    .hands-small:after {
      transform: rotate(22.5deg);
    }
    .hand-small:before {
      transform: rotate(67.5deg);
    }
    .hand-small:after {
      transform: rotate(112.5deg);
    }
    @keyframes rotatedial {
      0% {
        transform: rotate(35deg);
      }
      100% {
        transform: rotate(15deg);
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <div class="container">
      <div class="dial"></div>
      <div class="hands">
        <div class="hand"></div>
      </div>
      <div class="hands-small">
        <div class="hand-small"></div>
      </div>
    </div>

    enter image description here


    If you stumbled on this page looking for a SVG implementation, have a look at the below snippet:

    .separator {
        position: relative;
        width: 12px;
    }
    svg {
        position: absolute;
        top: 0px;
        left: 0px;
        height: 100%;
        width: 100%;
    }
    path {
        fill: url(#MyGradient);
    }
    path#shade {
        stroke: #2E2E2E;
        stroke-width: 3;
    }
    
    /* Just for the demo to style the divs and position */
    
    body {
        background: #333;
        font-family: Calibri;
        font-size: 18px;
    }
    .container {
        display: flex;
    }
    .container > .content {
        flex: 1;
        flex-grow: 1;
        color: white;
        margin: 20px;
    }
    <div class='container'>
        <div class='content'>Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.</div>
        <div class='separator'>
            <svg viewBox='0 0 10 200' preserveAspectRatio='none'>
                <defs>
                    <linearGradient id="MyGradient" x1=' 50% ' y1='0% ' x2='50% ' y2='100% '>
                        <stop offset="0%" stop-color="#333" />
                        <stop offset="100%" stop-color="#555" />
                    </linearGradient>
                </defs>
                <path d='M0,100 5,0 10,100 z' id='shade' />
                <path d='M0,100 5,0 10,100 5,200 z ' />
            </svg>
        </div>
        <div class='content '>Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.</div>
    </div>

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