skip to Main Content

I want to achieve the effect in the picture, it’s a button with hover effect. Before the hover, the button must have a triangle on the left like the above text in the picture, after the hover the triangle multiply to cover the hole button from left to right, the triangle must alternate like the button below in the picture.

enter image description here

this is my attempt of code

.triangle-btn {
                  position: relative;
                  display: inline-block;
                  padding: 10px 20px;
                  font-size: 16px;
                  color: #fff;
                  background-color: #007bff;
                  border: none;
                  outline: none;
                  cursor: pointer;
                }

                .triangle-btn:before {
                  content: "";
                  position: absolute;
                  top: 0;
                  left: 0;
                  width: 0;
                  height: 0;
                  border-top: 25px solid transparent;
                  border-right: 50px solid #007bff;
                  border-bottom: 25px solid transparent;
                }

                .triangle-btn:hover:before {
                  width: 100%;
                  transition: all 0.3s ease;
                }

                .triangle-btn:after {
                  content: "";
                  position: absolute;
                  top: 0;
                  right: 0;
                  width: 0;
                  height: 0;
                  border-top: 25px solid transparent;
                  border-left: 50px solid #007bff;
                  border-bottom: 25px solid transparent;
                }

                .triangle-btn:hover:after {
                  width: 100%;
                  transition: all 0.3s ease;
                }
<button class="triangle-btn">Hover Me!</button>

3

Answers


  1. Chosen as BEST ANSWER

    This is my solution so far if anyone interested

    .tr1,
    .tr2,
    .tr3,
    .tr4,
    .tr5,
    .tr6,
    .tr7,
    .tr8 {
      position: absolute;
      top: -6px;
      width: 40px;
      height: 40px;
      background-color: #04234a;
      clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
      visibility: hidden;
      opacity: 0;
      transition: visibility 0s, opacity 0.3s linear;
    }
    .tr1 {
      left: -50px;
      visibility: visible;
      opacity: 1;
    }
    .tr2 {
      left: -25px;
      clip-path: polygon(50% 100%, 0 0, 100% 0);
    }
    .tr3 {
      left: 0px;
      transition-delay: 0.05s;
    }
    .tr4 {
      left: 25px;
      clip-path: polygon(50% 100%, 0 0, 100% 0);
      transition-delay: 0.1s;
    }
    .tr5 {
      left: 50px;
      transition-delay: 0.15s;
    }
    .tr6 {
      left: 75px;
      clip-path: polygon(50% 100%, 0 0, 100% 0);
      transition-delay: 0.2s;
    }
    .tr7 {
      left: 100px;
      transition-delay: 0.25s;
    }
    .tr8 {
      left: 125px;
      transition-delay: 0.3s;
    }
    .sendbtn:hover .tr2,
    .sendbtn:hover .tr3,
    .sendbtn:hover .tr4,
    .sendbtn:hover .tr5,
    .sendbtn:hover .tr6,
    .sendbtn:hover .tr1 {
      visibility: visible;
      opacity: 1;
    }
    <button class="relative w-48 h-10 sendbtn ml-12">
                    <span
                      class="text-white z-10 absolute top-1 left-0 w-full text-left text-sm font-medium"
                      >Get Started</span
                    >
                    <span class="tr1"></span><span class="tr2"></span
                    ><span class="tr3"></span><span class="tr4"></span
                    ><span class="tr5"></span><span class="tr6"></span
                    ><span class="tr7"></span><span class="tr8"></span>
                  </button>


  2. To create a button hover effect with triangles in the background, you can use CSS to style the button and add a pseudo-element to create the triangles. Here’s an example:

    .button {
      position: relative;
      display: inline-block;
      padding: 10px 20px;
      background-color: #333;
      color: #fff;
      font-size: 18px;
      border: none;
      cursor: pointer;
      overflow: hidden;
    }
    
    .button::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      width: 0;
      height: 0;
      border-style: solid;
      border-width: 0 0 100px 100px;
      border-color: transparent transparent #fff transparent;
      transition: all 0.3s ease;
    }
    
    .button:hover::before {
      width: 100%;
      height: 100%;
      border-width: 0 0 0 100%;
    }
    <button class="button">Hover me</button>
    Login or Signup to reply.
  3. After spending too much time on this, I came up with the following that allows you to set:

    • the number of triangles visible in the expanded state, via --expandedTriangleCount,
    • the background-color via the --shapeColor custom property, or to set a linear-gradient – across all triangles – if --shapeColor2 is set (if it’s unset then a linear-gradient is still used, but it transitions from --shapeColor to --shapeColor,
    • the triangle-stroke color, --shapeStrokeColor; this is the color that separates the various triangles from their neighbours,
    • the width of the "stroke", via --shapeStrokeWidth
    • and the base-size of the triangles, with --vertexSize; the height of the triangles are calculated in CSS (with a hardcoded value of the square-root of 3, as sqrt() is yet to be implemented outside of Safari (at the time of writing)).
    /* a simple reset, to ensure all elements are being sized to include
       border-widths and padding in their assigned sizes; removing all
       default margin and padding from the elements: */
    *,
    ::before,
    ::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    /* setting the block-size of the <body> (in English this is vertical,
       and is the axis on which blocks are laid out) to fill the available
       page, and setting padding of 1rem on the same block-axis, this specifies
       the same padding for both margin-block-start, and margin-block-end
       (the top (start) and bottom (end), in English): */
    body {
      min-block-size: 100vh;
      padding-block: 1rem;
    }
    
    /* simple utility-classes to adjust the gradient direction (this is
       nice to have, but effectively irrelevant to the demo except for
       demonstrating how CSS custom properties can be used): */
    .to-r {
      --gradientDirection: to right;
    }
    
    .to-br {
      --gradientDirection: to bottom right;
    }
    
    .to-tr {
      --gradientDirection: to top right;
    }
    
    .to-tl {
      --gradientDirection: to top left;
    }
    
    .to-bl {
      --gradientDirection: to bottom left;
    }
    
    .to-l {
      --gradientDirection: to left;
    }
    
    .to-b {
      --gradientDirection: to bottom;
    }
    
    .to-t {
      --gradientDirection: to top;
    }
    
    /* this is where it starts to matter: */
    div[data-background] {
      /* setting a default gradient direction, in
         the event none is set elsewhere: */
      --defaultGradient: to bottom right;
      /* the custom property establish the inline
         size (the size of the element on the inline-
         axis, left-right in English) in terms of
         the number of triangles to show when the
         element is hovered: */
      --expandedTriangleCount: 5;
      /* using the square root of 3 (defined later, and
         hardcoded as sqrt() doesn't yet exist outside
         of Safari) multiplied by half the --vertexSize
         to calculate the height of the triangle: */
      --height: calc(var(--sqrtOf-3) * var(--vertexSize)/2);
      /* the color of the triangles: */
      --shapeColor: hsl(270deg 95% 90% / 0.9);
      /* the color of the "strokes" that define the
         triangles: */
      --shapeStrokeColor: hsl(0deg 100% 100% / 1);
      /* the width of that stroke: */
      --shapeStrokeWidth: 0.5rem;
      /* this is the square root of 3: */
      --sqrtOf-3: 1.73205;
      /* setting the transition-duration for the transitions: */
      --transitionDuration: 0.4s;
      /* the size of each vertex of the shape: */
      --vertexSize: 15rem;
    
      /* here we set the repeating various gradients; these
         gradients are at 60deg and 300deg (360deg - 60deg),
         as internal angles of triangles must sum 180deg, and
         equilateral triangles are also equiangular. There is
         no third gradient to form the bottom fo the triangle
         as the clip-path removes that portion of the image: */
      background-image:
        /* a linear gradient at 60deg, with every repetition separated
           by the --height custom property; this forms the lines of the
           right-most side of the triangles that have their point
           directed upwards:
           */
        repeating-linear-gradient(60deg, var(--shapeStrokeColor) 0 var(--shapeStrokeWidth), transparent var(--shapeStrokeWidth) var(--height)),
        /* as above, another linear gradient, this time at 300deg which forms
           the left-most side of the upward-pointing triangles:
           */
        repeating-linear-gradient(300deg, var(--shapeStrokeColor) 0 var(--shapeStrokeWidth), transparent var(--shapeStrokeWidth) var(--height)),
        /* this gradient forms the background-color/background-gradient
           (though it's obviously a gradient in all instances, if 
           --shapeColor2 is specified then the transition will run from
           --shapeColor to --shapeColor2; if not, then --shapeColor2
           defaults to --shapeColor so there's no apparent gradient: */
        linear-gradient(var(--gradientDirection, var(--defaultGradient)), var(--shapeColor), var(--shapeColor2, var(--shapeColor)));
      /* setting the height of the element to be equal to the height
         "altitude" of the triangle (using JavaScript to calculate this
         value pending a CSS implementation of sqrt(): */
      block-size: var(--height);
      /* using clip-path, and the polygon function, to trim the element
         to show only one instance of the triangle; the three point
         triangle is defined by a clip-path of four points in order
         to transition to the expanded state: */
      clip-path:
        polygon(
          /* we start in the lower-left of the element's box, setting
             the x-position equal to the --shapeStrokeWidth, and the
             y-position to the height of the element (100%) minus the
             --shapeStrokeWidth: */
          var(--shapeStrokeWidth) calc(100% - var(--shapeStrokeWidth)),
          /* these two points are in the same position at this point,
             because while they're defined differently, the calculation
             places them on the same point (barring sub-pixel rounding);
             both are positioned at 0 on the y-axis; the first
             has its x-popsition calculated as half of the --vertexSize
             property in relation to the left edge: */
          calc(var(--vertexSize)/2) 0,
          /* the second is positioned half the --vertexSize away from
             (before) the right edge (100%): */
          calc(100% - (var(--vertexSize)/2)) 0,
          /* here the x-position is 100% of the element's size minus the
             --shapeStrokeWidth, and the y-position is the same in order
             to clip out the bottom edge of the triangle: */
          calc(100% - var(--shapeStrokeWidth)) calc(100% - var(--shapeStrokeWidth))
        );
      /* using display grid for easy positioning of the contents: */
      display: grid;
      inline-size: var(--vertexSize);
      margin-block: 1rem;
      /* auto-margins on the inline axis to center the element(s) on
         that axis (horizontal, in English): */
      margin-inline: auto;
      /* centering the contents: */
      place-content: center;
      /* transitioning the inline-size with a duration of defined
         with the --transitionDuration custom property: */
      transition: inline-size var(--transitionDuration) linear;
    }
    
    /* the element containing text: */
    div[data-background] .text {
      /* transparent, with font-size of 0 in order to
         hide the text when it's not hovered: */
      color: transparent;
      font-size: 0;
      /* centering the text on the inline-axis: */
      text-align: center;
      /* transitioning the font-size: */
      transition: font-size var(--transitionDuration) linear;
    }
    
    /* styling the ::first-letter pseudo-element of
       the text:*/
    div[data-background] .text::first-letter {
      /* these styles are purely for visibility of the
         first letter, adjust to taste: */
      color: black;
      font-size: 1.2rem;
    }
    
    div[data-background]:hover .text {
      /* transitioning the text into visibility, via
         font-size: */
      color: currentColor;
      font-size: 1rem;
      transition: font-size var(--transitionDuration) var(--transitionDuration) linear;
    }
    
    div[data-background]:hover {
      /* the inline-size of the hovered-state is derived from the
         --expandedTriangleCount (with a default of 5) by the
         --vertexSize, to create an element that has a multiple
         of triangles; this sizes the lower-edge of the
         element, the upper row of triangles will one less than
         the set number; though the clip-path could be modified to
         adjust this: */
      inline-size: calc(var(--expandedTriangleCount) * var(--vertexSize));
      transition: inline-size var(--transitionDuration) linear;
    }
    <!-- using the style attribute to pass custom arguments in order to demonstrate the
         extensibility/use of this approach: -->
    <div style="--vertexSize:12rem" data-background="triangle">
      <span class="text">Simple button test</span>
    </div>
    <div style="--vertexSize:5rem" data-background="triangle">
      <span class="text">X</span>
    </div>
    <div style="--vertexSize:200px; --shapeColor: orange; --shapeColor2: red; --expandedTriangleCount: 3" data-background="triangle">
      <span class="text">warning</span>
    </div>
    <div style="--vertexSize:50px; --shapeColor: hsl(70deg 75% 70% / 0.9);" data-background="triangle"></div>
    <div style="--vertexSize:10ex; --shapeColor: #f904;" data-background="triangle"></div>
    <div style="--vertexSize:9ch; --expandedTriangleCount: 11" data-background="triangle"></div>

    JS Fiddle demo.

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search