1

I am trying to create an image before and after comparison slider in LWC. I am using the code from this guy (https://codepen.io/Coding-in-Public/pen/NWyjZwO) but when I put the component on a page the slider doesn't even move ( left to right or right to left ).

Edit : i am new to LWC, and without adding the window.onload=function(){ in the js file, the component was not even loading ( had errors ).

HTML :

<template>
    <main>
        <div class="container">
          <div class="image-container">
            <img
              class="image-before slider-image"
             src="https://i.picsum.photos/id/1015/6000/4000.jpg?hmac=aHjb0fRa1t14DTIEBcoC12c5rAXOSwnVlaA5ujxPQ0I"
              alt="color photo"
            />
            <img
              class="image-after slider-image"
              src="https://i.picsum.photos/id/1015/6000/4000.jpg?hmac=aHjb0fRa1t14DTIEBcoC12c5rAXOSwnVlaA5ujxPQ0I"
              alt="black and white"
            />
          </div>
          <!-- step="10" -->
          <input
            type="range"
            min="0"
            max="100"
            value="50"
            aria-label="Percentage of before photo shown"
            class="slider"
          />
          <div class="slider-line" aria-hidden="true"></div>
          <div class="slider-button" aria-hidden="true">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="30"
              height="30"
              fill="currentColor"
              viewBox="0 0 256 256"
            >
              <rect width="256" height="256" fill="none"></rect>
              <line
                x1="128"
                y1="40"
                x2="128"
                y2="216"
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="16"
              ></line>
              <line
                x1="96"
                y1="128"
                x2="16"
                y2="128"
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="16"
              ></line>
              <polyline
                points="48 160 16 128 48 96"
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="16"
              ></polyline>
              <line
                x1="160"
                y1="128"
                x2="240"
                y2="128"
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="16"
              ></line>
              <polyline
                points="208 96 240 128 208 160"
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="16"
              ></polyline>
            </svg>
          </div>
        </div>
      </main>
</template>

CSS :

    *,
*::after,
*::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.video-container {
  margin: 2rem;
  max-height: 300px;
}

iframe {
  apsect-ration: 16/9;
}

img {
  display: block;
  max-width: 100%;
}

main {
  display: grid;
  place-items: center;
  min-height: 100vh;
}

.container {
  display: grid;
  place-content: center;
  position: relative;
  overflow: hidden;
  border-radius: 1rem;
  --position: 50%;
}

.image-container {
  max-width: 800px;
  max-height: 90vh;
  aspect-ratio: 1/1;
}

.slider-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: left;
}

.image-before {
  position: absolute;
  inset: 0;
  width: var(--position);
  filter: grayscale(100%)
}

.slider {
  position: absolute;
  inset: 0;
  cursor: pointer;
  opacity: 0;
  /* for Firefox */
  width: 100%;
  height: 100%;
}

.slider:focus-visible ~ .slider-button {
  outline: 5px solid black;
  outline-offset: 3px;
}

.slider-line {
  position: absolute;
  inset: 0;
  width: .2rem;
  height: 100%;
  background-color: #fff;
  /* z-index: 10; */
  left: var(--position);
  transform: translateX(-50%);
  pointer-events: none;
}

.slider-button {
  position: absolute;
  background-color: #fff;
  color: black;
  padding: .5rem;
  border-radius: 100vw;
  display: grid;
  place-items: center;
  top: 50%;
  left: var(--position);
  transform: translate(-50%, -50%);
  pointer-events: none;
  /* z-index: 100; */
  box-shadow: 1px 1px 1px hsl(0, 50%, 2%, .5);
}

JS :

    import { LightningElement } from 'lwc';

window.onload=function(){
document.querySelector(".compare #compare-ip").addEventListener ("input", function(e){
document. querySelector(".compare .before.after"). style.width = (+e.target. value) +"px";
});
document. querySelector(".compare #compare-ip") .addEventListener ("change", function(e){
document. querySelector(".compare.before.after" ).style.width = (+e.target.value) +"px";
});

}
export default class BeforeAfterSlider extends LightningElement {}
2
  • Looking at your source code, sorry to say, but I'd very much recommend you'd give a Trailhead a go, or have a look at some LWC recipies. It's worth it. You will easily see what you should change in above sources afterwards. Jun 29, 2022 at 20:29
  • Yes you are right, i just started so i was experimenting, i would need to try the trailhead and look at some examples. Thanks a lot
    – Brian23Gt
    Jun 30, 2022 at 5:45

1 Answer 1

1

LWC doesn't work quite the same as vanilla JavaScript. I'd recommend that you attach an event listener directly to the slider, then handle the event.

<input
      type="range"
      min="0"
      max="100"
      value="50"
      aria-label="Percentage of before photo shown"
      class="slider"
      oninput={handleInput}
    />

handleInput(event) {
  this.template.querySelector('.container')
    .style.setProperty(
      '--position', 
      `${event.target.value}%`
    );
}

Note that I query the component every time not because it is necessary here, but because if I cached the queried component, and it gets re-rendered somehow, the code might stop working.

Demo.

1
  • Thanks a lot, your code worked perfectly. I have a lot to learn, and this will help for sure!
    – Brian23Gt
    Jun 30, 2022 at 5:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .