skip to Main Content

I’m trying to replicate the VueJS logo with a CSS-only approach, not by importing an SVG or anything.

I’ve use clippy to have some proper clip-path, but still there is no way for me to find the proper rotation between the arms of the logo.


This is what I tried so far

.wrapper {
  height: 100svh;
  display: flex;
  flex-direction: row;
  align-items: center;
  transform: rotate(-60deg)
}

.wrapper div {
  width: 250px;
  height: 45px;
}

.left {
  transform: rotate(-60deg) translate(60%, 200%) scale(-1);
}

.green {
  background-color: #42b883;
  clip-path: polygon(33px 0, calc(100% - 33px) 0, 100% 100%, 0% 100%);
}

.blue {
  background-color: #35495e;
  clip-path: polygon(
    66px 0,
    calc(100% - 66px) 0,
    calc(100% - 33px) 100%,
    33px 100%
  );
}
<div class="wrapper">
  <main class="left">
    <div class="blue"></div>
    <div class="green"></div>
  </main>
  <main class="right">
    <div class="blue"></div>
    <div class="green"></div>
  </main>
</div>

I’ve tried various translations, transforms etc, but none of them seem to be logical, while I thought that applying a 60-degree rotation would be enough.
Turns out it totally didn’t.

2

Answers


  1. If you want to go with the clip-path technique, that works, but I might stick to only using clip-path, as opposed to trying to rotate and mirror your figure path after you’ve created it. clip-path is powerful enough to handle it all. Refer to this MDN page for information on how to use clip-path with polygon() – it’s not overly difficult – it’s just a comma separated list of coordinate pairs where each value can simply be defined as a percentage.

    In the below example, I’m creating two divs, one for blue, and the other for green. I layer the two divs over each other and set their size to be the exact same.

    /*
    Layer the two divs over each other,
    and set the size of the divs.
    */
    .blue, .green {
      position: absolute;
      top: 0;
      left: 0;
      width: 512px;
      height: 444px;
    }
    
    .blue {
      background-color: #34495e;
      clip-path: polygon(
        20% 0%, /* top left */
        40% 0%,
        50% 23%, /* top of the inside of the V */
        60% 0%,
        80% 0%, /* top right */
        50% 60% /* bottom of the V */
      );
    }
    
    .green {
      background-color: #41b883;
      clip-path: polygon(
        0% 0%, /* top left */
        20% 0%,
        50% 60%, /* top of the inside of the V */
        80% 0%,
        100% 0%, /* top right */
        50% 100% /* bottom of the V */
      );
    }
    <div class="blue"></div>
    <div class="green"></div>

    If you instead want to go strong with the rotating/shifting stuff, here’s how you might go about doing that (without using clip-path).

    Step 1: Create a dark-blue div with a green bottom-border. Move and rotate it into position. The top will be cut off simply because it’s shooting out above the top of the page.

    /*
    A rotated dark-blue box with a light-green border
    under it. This is getting cropped by its #left-crop-container parent.
    */
    #left-content {
      position: relative;
      background-color: #34495e;
      width: 550px;
      height: 82px;
      left: -72px;
      top: 96px;
      border-bottom: 89px solid #41b883;
      transform: rotate(60deg);
    }
    <div id="left-content"></div>

    Step 2: Put our figure inside of a container. Give the container a fixed size, and configure it to crop anything that extrudes out of it (with overflow: hidden).

    In the below example, I’ll outline the box that does the cropping in red, so it’s easier to see what’s going on.

    /*
    The left half of the logo will be put inside of this box.
    Anything that hangs out will be cropped via the `overflow: hidden` rule
    */
    #left-crop-container {
      width: 256px;
      height: 445px;
      overflow: hidden;
      outline: solid red;
    }
    
    /*
    A rotated dark-blue box with a light-green border
    under it. This is getting cropped by its #left-crop-container parent.
    */
    #left-content {
      position: relative;
      background-color: #34495e;
      width: 550px;
      height: 82px;
      left: -72px;
      top: 96px;
      border-bottom: 89px solid #41b883;
      transform: rotate(60deg);
    }
    <div id="left-crop-container">
      <div id="left-content"></div>
    </div>

    Step 3: Now we just need to mirror it to the other side. I’m going to accomplish this by copy-pasting the exact same HTML, but I’ll put the pasted HTML inside of a container div that contains CSS to flip it.

    /*
    If the container is smaller than a logo
    (e.g. because you're using a really small screen)
    make sure the right half doesn't try
    to wrap under the left half.
    */
    #logo {
      text-wrap: nowrap;
    }
    
    /*
    Makes the mirrored right half appear to
    the right of the left half, instead of under it.
    */
    #logo > * {
      display: inline-block
    }
    
    /*
    The left half of the logo will be put inside of this box.
    Anything that hangs out will be cropped via the `overflow: hidden` rule
    */
    #left-crop-container {
      width: 256px;
      height: 445px;
      overflow: hidden;
    }
    
    /*
    A rotated dark-blue box with a light-green border
    under it. This is getting cropped by its #left-crop-container parent.
    */
    #left-content {
      position: relative;
      background-color: #34495e;
      width: 550px;
      height: 82px;
      left: -72px;
      top: 96px;
      border-bottom: 89px solid #41b883;
      transform: rotate(60deg);
    }
    
    /* Mirrors its content, and shifts it slightly */
    #mirror-contents-to-right {
      position: relative;
      transform: rotateY(180deg);
      left: -5px;
    }
    <div id="logo">
      <div id="left-crop-container">
        <div id="left-content"></div>
      </div>
      <div id="mirror-contents-to-right">
        <div id="left-crop-container">
          <div id="left-content"></div>
        </div>
      </div>
    </div>

    Ta-Dah!

    Login or Signup to reply.
  2. You can get it using a single div, using just 2 gradients:

    .vue {
        width: 500px;
        height: 500px;
        background-image: linear-gradient(60deg, transparent 54%, green 54%, green 70%, black 70%, black 85%, transparent 85%), linear-gradient(-60deg, transparent 54%, green 54%, green 70%, black 70%, black 85%, transparent 85%);
        background-size: 50% 100%, 50% 100%;
        background-position: 0 0, 100% 0;
        background-repeat: no-repeat;
        transform: scale(0.5);
    
    }
    <div class="vue"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search