Home > Blockchain >  Sveltekit app: Why does classList toggle only re-render if class was initially present?
Sveltekit app: Why does classList toggle only re-render if class was initially present?

Time:12-11

In my sveltekit app I have a page where I want to update the classList on some elements via the onclick function. For example:

page.svelte

<script>
    import { onMount } from 'svelte';
    onMount(() => {
        document.getElementById("container").onclick = function () {
          document.getElementById("card").classList.toggle("card-flipped");
        };
    })
  
</script>

I have the following page elements that this is applied to (this is a typical flip-card setup, but using a click to flip the card instead of the hover event which can be done in pure css):

page.svelte (cont'd)

  <div id="container" >
    <div id="card" >
      <div id="front" >
        <h4>question.</h4><br>
        Here is a question.
      </div>
      <div id="back" >
        <h4>answer.</h4><br>
        Here is an answer.
        </div>
    </div>
  </div>

And the following styles:

page.svelte (cont'd)

<style>  
  .fc-container {
    position: relative;
    margin: auto;
    height: 500px;
    width: 700px;
    margin-top: 50px;
  }
    
  .card {
    border: 1px solid gray;
    position: absolute;
    top: 0px;
    left: 0px;
    height: 100%;
    width: 100%;
    transform-style: preserve-3d;
  }
  
  .card-front,
  .card-back {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
    padding: 20px;
  }
  
  .card-front {
    background-color: white;
  }
  
  
  .card-back {
    background-color: #fafafa;
    transform: rotateY(180deg);
  }
  
  .card-flipped {
    transform: rotateY(180deg);
  }
  
  </style>
  

This works fine on its own (codepen here). But within the sveltekit app, the toggled class is not applied to the element (i.e. it is not being redrawn) even though I can see in the developer tools that the class list is being updated on the element.

However, if I apply the toggled style initially:

    <div id="card" >

Then the class toggling works as expected.

Can someone shed light as to why this is happening, whether this is expected behavior, and whether there is a work around other than making sure that all classes I want to toggle are present when the page is first rendered?

CodePudding user response:

Your Codepen demo works because it's not omitting the CSS class selector. Contrast that behavior with SvelteKit which, during compile/HMR, removes unused CSS selectors to save space in the bundle. If you don't use the selector at compile time, it won't be there at runtime, which means your JS won't have the class to act on.

If you installed SvelteKit with the eslint plugin for your IDE, you should be seeing warnings that you have an "Unused CSS selector ".card-flipped" which is then omitted by SvelteKit at compile time. If you didn't install the linter, you can see your (slightly modified) code in this REPL which simulates a SvelteKit dev environment and shows the unused css error in an orange bar, bottom left.

I've added some commented dummy code and an extra style for the dummy that will resolve the issue if uncommented.

<!--in HTML section of  page.svelte-->
<div id="dummy" >
/*in CSS section of  page.svelte*/
.dummy {
    display: false;
}

It's similar to your "workaround" but won't affect your real components/behavior. There are other means of overriding the css warning in the compiler, but my efforts in that direction didn't work out.

Note that I also had to ignore an a11y warning to run your code. I'm sure the effect you're after is cool, but it's probably cooler to make sure everyone who might visit your app can use it without difficulty. Besides, who doesn't want to include more users :)

  • Related