Home > database >  CSS - Chevron not rotating on itself
CSS - Chevron not rotating on itself

Time:10-02

I have a simple html element with a chevron that I want to rotate when the dropdown changes however instead of rotating on itself it's rotating at the tip of the chevron making it change position, I tried to use transform-origin but it still doesn't work, any ideas why?

html element:

<div :class="[{ 'opened': isOpen }]">
          <div
            class="title"
            @click="toggle()"  //The toggle will just toggle the isOpen property
          >
            {{ title }}
          </div>
 </div>

css:

.title {
    width: 100%;
    position: relative;
    margin-top: 5px;
    padding-right: 1.5em;
  
  &:after {
    content: "";
    background-image: url(data:image/svg xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14'><path d='M1.9 13.8c-.1.1-.3.2-.5.2s-.4-.1-.5-.2l-.7-.7c-.1-.2-.2-.4-.2-.6s.1-.4.2-.5l4.7-5L.2 2c-.1-.1-.2-.3-.2-.5s.1-.4.2-.5L.9.3c.1-.2.3-.3.5-.3s.4.1.5.2l5.8 6.2c.2.2.3.4.3.6 0 .2-.1.4-.2.5l-5.9 6.3z' fill='!262674'/></svg>);
    background-repeat: no-repeat;
    position: absolute;
    width: 1.5em;
    height: 1em;
    transition: transform .3s;
    margin-top: 5px;
    transform: rotate(90deg);
    transform-origin: center;
    top: calc(50% - .5em);
    right: 0;
  }
}

When the dropdown is open:

.opened {
  .title {
    transition: rotate 300ms ease-in;
    &:after {
      content: "";
      background-image: url(data:image/svg xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14'><path d='M1.9 13.8c-.1.1-.3.2-.5.2s-.4-.1-.5-.2l-.7-.7c-.1-.2-.2-.4-.2-.6s.1-.4.2-.5l4.7-5L.2 2c-.1-.1-.2-.3-.2-.5s.1-.4.2-.5L.9.3c.1-.2.3-.3.5-.3s.4.1.5.2l5.8 6.2c.2.2.3.4.3.6 0 .2-.1.4-.2.5l-5.9 6.3z' fill='!262674'/></svg>);
      background-repeat: no-repeat;
      position: absolute;
      width: 1.5em;
      height: 1em;
      transition: transform .3s;
      margin-top: 5px;
      transform: rotate(270deg);
      transform-origin: center;
      top: calc(50% - .5em);
      right: 0;
    }
   }
  }

CodePudding user response:

The :after had a width and height that was not exact to the image, so there was some whitespace that was transparent. I set a width and height to a pixel value that matched the svg ratio. There was a few other tweaks as well to reduce all of your compensation rules.

$('.title-container').click(function(){
  $(this).toggleClass('opened');
});
.title {
    width: 300px;
    position: relative;
    margin-top: 5px;
    padding-right: 1.5em;
    background: #e2e2e2;
}
  
.title:after {
    content: "";
    background-image: url("data:image/svg xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14'><path d='M1.9 13.8c-.1.1-.3.2-.5.2s-.4-.1-.5-.2l-.7-.7c-.1-.2-.2-.4-.2-.6s.1-.4.2-.5l4.7-5L.2 2c-.1-.1-.2-.3-.2-.5s.1-.4.2-.5L.9.3c.1-.2.3-.3.5-.3s.4.1.5.2l5.8 6.2c.2.2.3.4.3.6 0 .2-.1.4-.2.5l-5.9 6.3z' fill='!262674'/></svg>");
    background-repeat: no-repeat;
    position: absolute;
    width: 12px;
    height: 20px;
    transition: transform .3s;
    transform: rotate(90deg);
    top: calc(50% - 10px);
    right: 1rem;
    transform-origin: center;
    text-align: center;
}

.opened .title:after {
    transform: rotate(270deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="title-container">
  <div class="title">
    <h2>TITLE</h2>
  </div>
</div>

CodePudding user response:

Styllable SVG version with SMIL animation, wrapped in a modern native Web Component:

<style>
  svg-chevron { width: 99px; margin: 10px; cursor: pointer; background: pink }
  svg-chevron[rotate="90"]  { fill: green }
  svg-chevron[rotate="270"] { fill: red   }
</style>

<svg-chevron rotate=0></svg-chevron>
<svg-chevron rotate=90></svg-chevron>
<svg-chevron rotate=180 dur="2s"></svg-chevron>
<svg-chevron rotate=270></svg-chevron>
<svg-chevron></svg-chevron>

<script>
  customElements.define("svg-chevron", class extends HTMLElement {
    connectedCallback() {
      this.style.display = "inline-block";
      this.rotation = Number(this.getAttribute("rotate") || 90); // initial rotation
      this.innerHTML = `<svg style="vertical-align:top" viewBox='0 0 140 140'><path d='m49 138c-1 1-3 2-5 2s-4-1-5-2l-7-7c-1-2-2-4-2-6s1-4 2-5l47-50-47-50c-1-1-2-3-2-5s1-4 2-5l7-6c1-2 3-3 5-3s4 1 5 2l58 62c2 2 3 4 3 6c0 2-1 4-2 5l-59 63z'>`  
        `<animateTransform type="rotate" from="${this.rotation} 70 70" to="${this.rotation} 70 70" dur="0.5s" additive="sum" repeatCount="once" fill="freeze" attributeType="xml" attributeName="transform"/></path></svg>`;
      this.onclick = (evt) => (evt.preventDefault(), this.rotate());
    }
    rotate(deg = 180) {
      let animate = this.querySelector("animateTransform");
      animate.onend = (evt) => this.setAttribute("rotate", this.rotation);
      animate.setAttribute("from", `${this.rotation} 70 70`);
      this.rotation = (this.rotation   deg) % 360;
      animate.setAttribute("to", `${this.rotation} 70 70`);
      animate.setAttribute("dur", this.getAttribute("dur") || ".5s");
      animate.beginElement(); 
    }
  })
</script>

  • Related