Looking to improve page speed by using rel="preload" to specify the order in which CSS files should be loaded on our site. The idea is that we would preload our global styles and then preload our hero area styles (as this is the most important element on the page to our marketing team).
We use Sass and follow a pretty typical set-up where each component or module on our site is chunked out into it's own partial .scss file and then imported (#import) into our main styles.scss file.
We compile the styles.scss file via Gulp into a single minified CSS file that contains all of the styles for the site (styles.min.css)
Example: current styles.scss file
//Shared Global Styles
#import "partials/reset"
#import "partials/variables"
#import "partials/typography"
//Individual Components and Modules
#import "partials/buttons"
#import "partials/cards"
etc...
This is what the Sass tasks in our Gulpfile look like:
gulp.task('styles:sass', ['svg'], function() {
const outputStyle = 'expanded';
const path = (watching) ? devCSSPath : buildCSSPath;
const building = (watching) ? false : true;
return gulp.src(['src/sass/*.scss', 'src/apps/*/styles/*.scss'])
.pipe(gulpif(watching, sourcemaps.init()))
.pipe(sass({
outputStyle: outputStyle,
includePaths: [kdsRoot] }).on('error', sass.logError))
.pipe(gulpif(watching, sourcemaps.write('maps')))
.pipe(gulpif(building, rename((path) => {
path.basename += ".min";
})
))
.pipe(gulp.dest(path));
});
gulp.task('styles:postcss', ['styles:sass'], function() {
const path = (watching) ? devCSSPath : buildCSSPath;
const plugins = [
autoprefixer({ grid: true}),
pixelsToRem({ base: 16 })
];
return gulp.src([path + '*.css', path + '**/*.css'],{base: './'})
.pipe(postcss(plugins))
.pipe(gulp.dest('./'))
});
I want to create 3 different stylesheets (2 of which I will preload):
globals_preload.scss
//Shared Global Styles
#import "partials/reset"
#import "partials/variables"
#import "partials/typography"
hero_preload.scss
//Styles for the hero module
#import "partials/hero"
styles.scss
//Styles for the rest of the components/modules
//Global .scss files removed
//Individual Components and Modules
#import "partials/buttons"
#import "partials/cards"
etc...
I would ideally load the 3 stylesheets like so:
<head>
<link rel="preload" href="globals_preload.min.css" as="style">
<link rel="preload" href="hero_preload.min.css" as="style">
<link rel="stylesheet" href="styles.min.css">
</head>
Here lies the problem; Every component or module is dependent on the global styles and variables, but I don't want to load the global styles twice (by having them imported both in globals_preload.scss and styles.scss); If I remove the import statements for the global styles from style.scss my compiler will fail because the subsequent modules will not be able to find the sass variable they are looking for.
Is there anyway for this approach to work with Sass? Is there a way to remove certain partials from the compiled CSS via Gulp? I'm open to any suggestions.
Related
First of all I'd like you guys to be gentle. I haven't been coding much in recent year and since gulp update when then changed syntax to writing functions and exporting I somehow made it work then and left with no changes up to this point, no clue if they changed something else. I've been happy with what it is right now, but I have no idea how to make it work the other way.
So anyway I'm working on a project right now, where there will be many htmls, and each one will have quite different styles, but some will be common. I want to make a main.scss file with common styles for each html, but I want to make a separate scss with styles specific to each html. This way in the end I want to have a separate css file made from a specific scss with same name combined with main.scss, so that it won't have to download a single large file, but only styles I need.
Example:
main.scss
01.scss
02.scss
03.scss
will compile to:
01.css ( main.scss + 01.scss )
02.css ( main.scss + 02.scss )
03.css ( main.scss + 03.scss )
This is my gulpfile right now:
const gulp = require('gulp');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
function style() {
return gulp.src('./scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'))
.pipe(browserSync.stream());
}
function watch() {
browserSync.init({
server: {
baseDir: './'
}
});
gulp.watch('./scss/**/*.scss', style);
gulp.watch('./*.html').on('change', browserSync.reload);
gulp.watch('./js/**/*.js').on('change', browserSync.reload);
}
exports.style = style;
exports.watch = watch;
If you have an idea how to do it in a better way I would really appreciate it.
I think you will have to import your main.scss into each of your other files and exclude main.scss from your gulp.src.
function style() {
return gulp.src(['./scss/**/*.scss', '!./scss/**/main.scss'])
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'))
.pipe(browserSync.stream());
}
'!./scss/**/main.scss' this negates or excludes that file from being passes into this task - I assumed main.scss was in the same folder as your other scss files, if that is not the case you will have to modify the path.
Then #import main.scss into each of your 01.scss, 02.scss, etc. files:
#import "main.scss"; // also assumes in same folder
You can put this import statement anywhere in the file, if it is first any of main.scss styles will be overridden by conflicting styles in the rest of the 0x.scss file. If you put the import statement at the end, then main.scss styles will override any previous conflicting styles.
Note: you should really be using #use instead of #import and gulp-dart-sass instead of gulp-sass at this point. See sass #use rule.
// in your gulpfile.js
const sass = require('gulp-dart-sass'); // once installed
#use "main.scss"; // must be at top of each scss file, such as 01.scss
Is it possible to import css-files to a separate layout so that styles are applied only to one layout without affecting others?
I found this solution.
Rename ".css" files to ".scss".
In your layout add the wrapper block with custom class "my-class".
layouts/AuthLayout:
<template>
<div class="auth-layout">
<section>
<Nuxt/>
</section>
</div>
</template>
Then add a style section. This uses SCSS features and the v-deep directive.
layouts/AuthLayout:
<style scoped lang="scss">
.auth-layout {
&::v-deep {
#import '~assets/path/to/style.scss';
#import '~assets/path/to/custom.scss';
// ...
}
}
</style>
I hope it would be helpful for somebody.
If your style files have .css extension you can put them on static directory and address in your layout head function or object in this way (my file is in static/css/main.css directory)
return {
link: [
//you shouldn't mention ~/static itself
{ rel: 'stylesheet', href: '/css/main.css' },
],
};
if your file has .scss extension or any other preprocessor you can put it in assets directory cause webpack compile files on this directory.
I have a Vue app composed of several standard .vue files like this:
<template>
<h1>My App</h1>
</template>
<script>
export default {
name: 'app',
data () {
return {
cssTheme: 'default-theme'
};
}
}
</script>
<style lang="less">
#import "assets/constants";
html, body {
color: #color-ui-text;
}
</style>
In my assets/constants.less file I have defined many css variables to be used by less (colours, fonts and so on).
I want to give my app a serie of graphical "themes" that can be changed dynamically.
Given the variable cssTheme that I can read / set / change from the interface (and set it to strings like "green-theme", "vintage-theme", "default-theme"), how can I import and apply on the fly the appropriate less file into the <style> part of the .vue file? For instance, the user selects the "green-theme" and I want to switch the default imported file #import "assets/constants"; to #import "assets/constants-green"; where, for example, #color-ui-text; is set to dark green instead of the standard black.
If you use vue cli, you can use something like this:
module.exports = {
css: {
loaderOptions: {
sass: {
data: `
#import "assets/constants";
`
}
}
}
};
It will automatically add #import "assets/constants"; in each sass file
Note: i use sass in example
more about this you can find here:
loaderoptions
What is the best way to have a global css file in Vuejs for all components? (Default css like bg color, button styling, etc)
import a css file in the index.html
do #import in main component
put all the css in the main component (but that would be a huge file)
Import css in your index.html, but if you're using webpack you can just import your stylesheets in your main js config and all your components will get the css.
As comments below suggested if using webpack adding this to main.js works:
import './assets/css/main.css';
I found the best way is to create a new file in the assets folder, I created as global.css but you can name anything of your choice. Then, import this file global.css file in the main.js.
Note: Using this approach you can also create multiple files if you think the global.css is getting really large then simply import all those files in the main.js.
#\assets\global.css
/* move the buttons to the right */
.buttons-align-right {
justify-content: flex-end;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './routes'
Vue.config.productionTip = false
// Importing the global css file
import "#/assets/global.css"
new Vue({
router,
render: h => h(App)
}).$mount('#app')
In App.vue you can add a style property to declare you CSS file:
<style>
#import './assets/css/global.css';
</style>
You can also do something like this: https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/
My folders are mostly structured like this:
- src
- assets
- _global.scss
- _colors.scss
- _fonts.scss
- _paragraphs
- index.scss // <-- import all other scss files.
This also works with normal css.
create a new css file in your assets folder for example : global.css
import "global.css" to main.js
import '#/assets/main.css';
There are to two ways, as I know, to achieve this.
Approach 1
Utilize vue.config.js configuration, less config can also be replaced with sass:
module.exports = {
css: {
loaderOptions: {
less: {
additionalData: `#import '#/style/common.less';`
}
}
}
}
Approach 2
In your .vue file, make your style looks like this:
<style lang="less">
#import (reference) "../../style/variables.less";
#app {
background: #bgColor;
}
</style>
Note: the (reference) flag is used to make variables defined in variables.less take effect. If you don't have variables, #import "../../style/variables.less"; is sufficient to do the trick.
For your reference, you can also take a look at this link:
https://github.com/tjcchen/vue-practice/tree/master/multipage-app
Sass announced their new module system. Why don't you use #use and #forward?
My approach is the best way to use scss with vite.
Use defineConfig to setup global scss (colors, mixin) and reuse in all component without import
css: {
preprocessorOptions: {
scss: {
additionalData: `#use "~/styles/main.scss" as *;`,
},
},
},
Here: code sandbox
create a vue.config.js file in your root directory
Create a styles folder inside your src folder and you can create your global style file here for example base.scss
to use scss install two dependencies
npm install node-loader sass-loader
Inside your vue.config.js paste code from below
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `#import "#/styles/base.scss";`
}
}
}
};
I am using node-sass to mock my CDN builds and I am converting my CSS to
a modular Sass design. Basically my setup involves brand sites overwriting
the common styles.
I want to do something like this in the brand folder
#import "../common/global-config";
#import "brand-config";
#import "../common/common";
// brand specific styles here
this file would live at /css/brand-name/brand.scss
the other files would live in /css/common/_common.scss
my node-sass setup looks something like this
function compileSassFile(includes, path, callback) {
if (!fs.existsSync(path)) {
return null;
}
var css = sass.renderSync({
file: path,
success: callback,
outputStyle: 'expanded',
includePaths: includes
});
return css;
}
// bundlePath = 'css', dirName = '/brand-name'
compileSassFile([path.join(bundlePath), path.join(bundlePath, 'common'), path.join(bundlePath, dirName)], path.join.apply(bundlePath, [dirName, 'brand.scss']));