Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build removes style tags inside template #6645

Closed
ebspeter opened this issue Nov 1, 2019 · 3 comments
Closed

Build removes style tags inside template #6645

ebspeter opened this issue Nov 1, 2019 · 3 comments

Comments

@ebspeter
Copy link

ebspeter commented Nov 1, 2019

Version

v2.10.2

Reproduction link

https://github.com/ebspeter/nuxt-build-remove-style

Steps to reproduce

  1. npm install
  2. npm run build && npm run start
  3. Open localhost:3000

What is expected ?

Red background on body

What is actually happening?

The style from pages/index.vue has been removed.

<style>
      body { background: red; }
</style>

Additional comments?

This was introduced in 2.10.0 and still works in 2.9.2.

npm run dev and npm run generate works normally.

This bug report is available on Nuxt community (#c9973)
@ghost ghost added the cmty:bug-report label Nov 1, 2019
@manniL
Copy link
Member

manniL commented Nov 1, 2019

This shouldn't have worked in the first place. Vue should also emit a warning in dev mode:

Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <style>, as they will not be parsed.

@manniL manniL closed this as completed Nov 1, 2019
@ebspeter
Copy link
Author

ebspeter commented Nov 1, 2019

@manniL Got it.

But then how to accomplish dynamic styles with media queries? That is my use-case for having to do this at all.

As long as it works with npm run generate i'm golden....

DynamicBackground.vue:

<template>
  <div>
    <div v-if="background && background.placeholder" class="background placeholder" :class="instanceScope">
      <style>
        .background.placeholder.{{ instanceScope }} {
          background-size: {{ image.size || 'cover' }};
          background-image: url('{{ background.placeholder }}');
        }
      </style>
    </div>

    <div v-if="background && background.small" class="background" :class="{ [instanceScope]: true, parallax }">
      <style>
        .background.{{ instanceScope }} {
          background-size: {{ image.size || 'cover' }};
        }
        @media only screen and (min-width: 1px) {
          .background.{{ instanceScope }} {
            background-image: url('{{ background.small }}');
            background-position: {{ image.position && image.position.small || "center center" }};
          }
        }
        @media only screen and (min-width: 480px) {
          .background.{{ instanceScope }} {
            background-image: url('{{ background.medium }}');
            background-position: {{ image.position && image.position.medium || "center center" }};
          }
        }
        @media only screen and (min-width: 640px) {
          .background.{{ instanceScope }} {
            background-image: url('{{ background.large }}');
            background-position: {{ image.position && image.position.large || "center center" }};
          }
        }
        @media only screen and (min-width: 992px) {
          .background.{{ instanceScope }} {
            background-image: url('{{ background.xlarge }}');
            background-position: {{ image.position && image.position.xlarge || "center center" }};
          }
        }
      </style>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    image: {
      type: Object,
      default: () => {}
    },
    parallax: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    background() {
      try {
        if (this.image && this.image.mobile && this.image.mobile.length !== 0) {
          const image = require(`@/assets${this.image.desktop.path}?sizes[]=1200`)
          const imageMobile = require(`@/assets${this.image.mobile.path}?sizes[]=480,sizes[]=640,sizes[]=992`)
          const fallback = imageMobile.images[imageMobile.images.length - 1].path
          const num = imageMobile.images.length
          return {
            placeholder: imageMobile.placeholder,
            small: imageMobile.images[0].path,
            medium: num > 1 ? imageMobile.images[1].path : fallback,
            large: num > 1 ? imageMobile.images[2].path : fallback,
            xlarge: image.images[0].path
          }
        } else if (this.image && this.image.desktop && this.image.desktop.length !== 0) {
          const image = require(`@/assets${this.image.desktop.path}?sizes[]=480,sizes[]=640,sizes[]=992,sizes[]=1200`)
          const fallback = image.images[image.images.length - 1].path
          const num = image.images.length
          return {
            placeholder: image.placeholder,
            small: image.images[0].path,
            medium: num > 1 ? image.images[1].path : fallback,
            large: num > 2 ? image.images[2].path : fallback,
            xlarge: num > 3 ? image.images[3].path : fallback
          }
        }
      } catch (error) {
        console.log(error, this.image)
        return null
      }
      return null
    },
    instanceScope() {
      return `${this.$options._scopeId}-${this._uid}`
    }
  }
}
</script>

<style lang="scss" scoped>
.background {
  background-position: center;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  &.parallax {
    position: absolute;
    background-attachment: fixed;
  }
}
</style>

@ebspeter
Copy link
Author

ebspeter commented Nov 6, 2019

Found the solution here: https://stackoverflow.com/a/57331310/6096659

To anyone running into this, just use component:

<template>
  <component :is="'style'">
    body { background: red; }
  </component>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants