I'm trying to convert my Nuxt application to Sapper and I've come across a bit of a roadblock.
In my Nuxt application, I have a layout file which simply includes bulma's SASS version:
<style lang="scss">
@import '~bulma/scss/_all';
</style>
This is possible, and allows the styles to be used across the application, because Vue doesn't scope styles by default.
I'll caveat this by saying that I prefer scoped styles by default, but I feel like there needs to be a way to unscope the styles when necessary. Because of the way Sapper/Svelte handles styles, and scopes them, including bulma in a similar way to the above means that Svelte will scope all the styles, and then remove nearly all of them as it sees them as "unused".
This means I end up with an application with no styles!
Right now this is a roadblock to my conversion, as I can't see a workaround (other than some horrendous external compilation with gulp or similar and then including the compiled css in my head - which I really want to avoid as it takes from the speed of Sapper's development, as well as adding complexity where it really shouldn't be.
Any tips? Or is there a feature / capability missing from Sapper here?
In the Svelte docs there's a section about using :global() to ignore Svelte's scoping mechanism. You need to apply this to each selector you want globally scoped. It can get a bit tedious so I wrote a svelte style preprocessor which does this automatically when the style block has a "global" attribute, eg. <style global>... no docs though as it's just something we've been using internally and it's more for PostCSS.
For SCSS support you might want to have a look at https://github.com/kaisermann/svelte-preprocess and https://github.com/ls-age/svelte-preprocess-sass. Or if you want to write your own preprocessor see https://github.com/sveltejs/svelte#preprocessor-options.
It's also worth mentioning you can import your global styles in a JS file and then handle it with webpack/rollup plugins. This is actually what we do most of the time.
A caveat is _all_ the styles will be included so I recommend using a tool like https://github.com/FullHuman/purgecss to remove any unused styles.
Hi @MaxMilton - thanks for your help, but sadly none of these solutions fix the core issue. I'm quite happily using scss within components, but I need to include the bulma library. I can't (and shouldn't) wrap the entire library in :global { }.
@MaxMilton this is basically what I'm doing now, based on another project I have found, but writing a build file and parallel building my scss outside the app with a separate watcher and then including the compiled css file out of band... is a total hack.
This feels like it should be a simple, easy thing that should be supported out of the box. I would vouch that most non-trivial projects are based on a CSS library (Bootstrap, Bulma, Pure, Semantic etc) - with a customisation file.
In that case it's probably best to import global styles it in your src/client.js (assuming you're using sapper-template) and handle via webpack/rollup. Then in your components you can import variables as you need them.
@MaxMilton thanks - I'll give that a go. If it works then it's more a matter of documentation than it is functionality.
Probably worth updating this with my current solution. I still think this should be native to Sapper as I think it's quite a common usecase and therefore having to get people rolling up their sleeves and fumbling with webpack to do this isn't ideal, but:
https://github.com/kaisermann/svelte-preprocess
Is a very nice solution to getting preprocessed styles working in components, and also allowing processing and live-reloading of a third-party css framework like Bulma / Bootstrap / Semantic.
@antony I had the same issue with Bulma and global CSS. By the way I'm using svelte-preprocess as well. Here is how I made it work by generating a global.css file with Bulma stuff:
Install the following dependencies:
npm i -D node-sass postcss cssnano bulma
Add the following lines to your webpack.config.js file:
const fs = require('fs')
const sass = require('node-sass')
const postcss = require('postcss')
const cssnano = require('cssnano')({preset: 'default'})
// generating global css file https://github.com/sveltejs/sapper/issues/357
sass.render({
file: './src/style/global.sass',
indentedSyntax: true,
outFile: './static/global.css'
}, function (error, result) {
if (!error) {
postcss([cssnano])
.process(result.css, {
from: './static/global.css',
to: './static/global.css'
})
.then(result =>
fs.writeFile('./static/global.css', result.css, function (err) {
if (err) {
console.log(err)
}
})
)
} else {
console.log(error)
}
})
And create a /src/style/ subdirectory with the 3 following files:
// Import a Google Font
@import url('https://fonts.googleapis.com/css?family=Nunito:400,700')
// Set your brand colors
$purple: #8A4D76
$pink: #FA7C91
$brown: #757763
$beige-light: #D0D1CD
$beige-lighter: #EFF0EB
// Update Bulma's global variables
$family-sans-serif: "Nunito", sans-serif
$grey-dark: $brown
$grey-light: $beige-light
$primary: $purple
$link: $pink
$widescreen-enabled: false
$fullhd-enabled: false
// Update some of Bulma's component variables
$body-background-color: $beige-lighter
$control-border-width: 2px
$input-border-color: transparent
$input-shadow: none
// Import only what you need from Bulma
@import "../../node_modules/bulma/sass/utilities/_all.sass"
@import "../../node_modules/bulma/sass/base/_all.sass"
@import "../../node_modules/bulma/sass/elements/button.sass"
@import "../../node_modules/bulma/sass/elements/container.sass"
@import "../../node_modules/bulma/sass/elements/form.sass"
@import "../../node_modules/bulma/sass/elements/title.sass"
@import "../../node_modules/bulma/sass/components/navbar.sass"
@import "../../node_modules/bulma/sass/layout/hero.sass"
@import "../../node_modules/bulma/sass/layout/section.sass"
@charset "utf-8"
@import "./variables"
@import "./bulma"
// your global styles
p.foo
color: red
and in your .html files (if you use svelve-preprocess) use
<style lang="sass">
@import "../style/variables"
p.foo
color: $primary
</style>
Note that you have to re-run npm run dev every time you modify these global Bulma files.
Hope it helps.
Waiting for #357 …
I used @MaxMilton 's code and created this preprocessor which will make any css code global including support for external files and postcss plugins:
https://www.npmjs.com/package/svelte-preprocess-css-global
Probably worth updating this with my current solution. I still think this should be native to Sapper as I think it's quite a common usecase and therefore having to get people rolling up their sleeves and fumbling with webpack to do this isn't ideal, but:
https://github.com/kaisermann/svelte-preprocess
Is a very nice solution to getting preprocessed styles working in components, and also allowing processing and live-reloading of a third-party css framework like Bulma / Bootstrap / Semantic.
Hey man, can you share how you implemented this? I'm new to this build step thing in web development, forgive my ignorance.
Thanks in advance.
@jaybeemind svelte-preprocess has some excellent documentation about how to integrate it into rollup/webpack, you'd just need to follow it. If you need more help - come and talk to us in chat.
To those that would need a simple solution for this (using rollup template), with help from @antony , I was able to do it like this:
you will need:
then in your rollup.config.js file, add these:
...
import autoPreprocess from 'svelte-preprocess'
const preprocessOptions = {
transformers: {
scss: {
includePaths: [
'node_modules',
'src'
]
},
postcss: {
plugins: [
require('autoprefixer'),
]
}
},
}
...
export default {
client: { // (and probably 'server' too)
...
svelte({
...
preprocess: autoPreprocess(preprocessOptions)
}),
after that, I added a style directory under src, and made a main.scss file.
inside the main.scss file, mine looks like these atm:
@import "../../node_modules/spectre.css/src/spectre.scss";
then import it in _layout.svelte
<style global lang="scss">
@import './style/main.scss';
...
I came from Vue.js and was impressed by how simple it is to do things with svelte.
I hope many would adapt sapper too, would love for it to mature.
EDIT: Removed transformers as per the authors message on discord.
You can do it this way too:
const preprocessOptions = {
scss: {
includePaths: [
'node_modules',
'src'
]
},
postcss: {
plugins: [
require('autoprefixer'),
]
}
}
You shouldn't need ../../node_modules/ prefixing your scss path. I believe that includePaths makes this possible.
@jaybeemind Thanks for this solution. I have to hit refresh for the changes to show, is that the expected behavior? Maybe I did something wrong.
@YogliB I got it working, The code for Svelte and Sapper are different. https://github.com/kaisermann/svelte-preprocess#with-sapper
@jaybeemind Tried doing something like that, in order to use Ionic 4 with Sapper and it didn't work...
You shouldn't need
../../node_modules/prefixing your scss path. I believe thatincludePathsmakes this possible.
I see, thanks! But honestly, I only did it that way because of vscode autocomplete lol 🤣
@jaybeemind Tried doing something like that, in order to use Ionic 4 with Sapper and it didn't work...
Can't help bro unless we see what you did.
Edit:
So this seems to not be possible at the moment https://github.com/kaisermann/svelte-preprocess/issues/58
Original:
is there a way to avoid importing the variables.scss in every
Most helpful comment
@fanckush For scss/sass, you can prepend the
@import 'variables.scss'with thedataprop: