Css-loader: animation names in :global scope are rewritten

Created on 11 Mar 2016  路  10Comments  路  Source: webpack-contrib/css-loader

Source file (mixed scopes)

// file: main.scss
:global {
    .spin {
        animation: spin 1s infinite linear;
    }
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
}

.example {
    width: 4rem;
    height: 4rem;
    background: red;
}

With the source file above, I expect to find both .spin and @keyframes spin written into the global css scope. Instead I get spin and @keyframes QaBLEFqXSeSWZkvccbzsW.

This becomes really problematic when trying to import 3rd party css that defines their own animations.

Output

.spin {
  animation: spin 1s infinite linear; }

@keyframes QaBLEFqXSeSWZkvccbzsW {
  0% {
    transform: rotate(0deg); }
  100% {
    transform: rotate(360deg); } }

._1zRVcLYUvZ_iPce6xumbp9 {
  width: 4rem;
  height: 4rem;
  background: red; }

Loader config

{
    test: /.scss$/,
    loader: 'style!css?modules!sass'
}
Bug

Most helpful comment

@at0g - I was having trouble with this when using :local since our project doesn't have local css turned on by default. You might want to try this instead:

// file: main.scss
:global {
    .spin {
        animation: spin 1s infinite linear;
    }
    @keyframes :global(spin) {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
}

When I swapped :global for :local, the @keyframes animation name was renamed properly in both the declaration and within the class I was using it in.

Here's my setup:

:local {
    @keyframes :local(spin) {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
    .spinnerWrapper {
        background: none;
        position: relative;
        width: 200px;
        height: 200px;
    }
    .spinner {
        animation: spin 1s linear infinite;
    }
}

which output to:

@keyframes _spinner__spin___QWBLz {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

._spinner__spinnerWrapper___rKp5P {
  background: none;
  position: relative;
  width: 200px;
  height: 200px;
}

._spinner__spinner___3jLpF {
  animation: _spinner__spin___QWBLz 1s linear infinite;
}

All 10 comments

@at0g - I was having trouble with this when using :local since our project doesn't have local css turned on by default. You might want to try this instead:

// file: main.scss
:global {
    .spin {
        animation: spin 1s infinite linear;
    }
    @keyframes :global(spin) {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
}

When I swapped :global for :local, the @keyframes animation name was renamed properly in both the declaration and within the class I was using it in.

Here's my setup:

:local {
    @keyframes :local(spin) {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
    .spinnerWrapper {
        background: none;
        position: relative;
        width: 200px;
        height: 200px;
    }
    .spinner {
        animation: spin 1s linear infinite;
    }
}

which output to:

@keyframes _spinner__spin___QWBLz {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

._spinner__spinnerWrapper___rKp5P {
  background: none;
  position: relative;
  width: 200px;
  height: 200px;
}

._spinner__spinner___3jLpF {
  animation: _spinner__spin___QWBLz 1s linear infinite;
}

@hellatan Thanks, but it does not really solve the issue (which is the animation name being rewritten in the global scope).

My expectation is that styles within :local or :global scope would be renamed consistently - in most cases they are, but not with animation names.

@at0g ya that's a good point - it is a non-obvious workaround. Are there any other keywords/characters other than @keyframes that could be an issue? I'm imagining that it's only seeing ., #, [ and alphanumeric values to apply the local/global css algorithm to.

If you want to have global class for animation you can use:

:global {
  .fadeIn :local {
    animation: fadeIn 2.5s ease-out;
  }
  @keyframes fadeIn {
    to {
      opacity: 1;
    }
  }
}

which results in:

.fadeIn {
    animation: animations__fadeIn___2pADx 2.5s ease-out; 
}
@keyframes animations__fadeIn___2pADx {
  from {
    opacity: 0; }
  to {
    opacity: 1; } 
}

If you use shorthand property for animations, be careful to put animation-name as the first one

This worked for me

@-webkit-keyframes :local(animatetop) {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}
@keyframes :local(animatetop) {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}
:local(.modalContent) :local{
    position: relative;
    background-color: white;
    margin: auto;
    padding: 0;
    border: 1px solid #888;
    width: 500px;
    min-height:300px;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
    -webkit-animation-name: animatetop;
    -webkit-animation-duration: 0.4s;
    animation-name: animatetop;
    animation-duration: 0.4s
}

The output was: (if that's what you were trying to accomplish)

@-webkit-keyframes _31eoHIHwv5wTOt_wePBEKx {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}
@keyframes _31eoHIHwv5wTOt_wePBEKx {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}
._3X1GGZ3CQqrjQ7gOsJ1Vev{
    position: relative;
    background-color: white;
    margin: auto;
    padding: 0;
    border: 1px solid #888;
    width: 500px;
    min-height:300px;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
    -webkit-animation-name: _31eoHIHwv5wTOt_wePBEKx;
    -webkit-animation-duration: 0.4s;
    animation-name: _31eoHIHwv5wTOt_wePBEKx;
    animation-duration: 0.4s
}
// file: main.scss
:global {
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
    .spin :local{
        animation: spin 1s infinite linear;
    }
}

That's what I did.

Had a similar issue but ensuring the animation name (as suggested by @dominik791) was specified as the first property in the animation shorthand fixed it.

Problem in https://github.com/css-modules/postcss-icss-selectors, looks already fixed (https://github.com/css-modules/postcss-icss-selectors/pull/49), if problem still exists, please create in issue in https://github.com/css-modules/postcss-icss-selectors

I fixed the issue in my project by replacing

.example {
   animation: 0.5s ease-out fadeIn;
}

with

.example {
   animation: fadeIn 0.5s ease-out;
}

For reference, I found this issue while debugging and documented several approaches here: https://gravitydept.com/blog/keyframe-animations-in-css-modules

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cuiyue picture cuiyue  路  3Comments

kcjonson picture kcjonson  路  3Comments

heldrida picture heldrida  路  4Comments

fengyun2 picture fengyun2  路  4Comments

Bhushankumar-pawar picture Bhushankumar-pawar  路  3Comments