Aurelia, scoped css - css

I am very new to Aurelia, and new web development in general (nodejs, gulp, and so on).
Thanks to the Aurelia CLI it was easy for me to setup a nice Aurelia project for Visual Studio Code using Typescript + SASS.
I thought it would be a good idea (but please tell me if it is not a good idea :) to use scoped css. There is already much information about this subject, but it is hard to find something that I can actually use. So I thought I would do it myself in the following way:
I have general stylesheets that can be imported "anywhere". Nothing new needs to be done to do this.
There will be component specific stylesheets that match the
component name + ".scss". So e.g. if there is a view + model like:
component.ts, component.html, there can be a component.scss which will contain styling that is specific for component.ts and component.html and thus should be scoped to this component.
I've tried to use style scoped html tags but this is not widely supported by browsers (and seems to be dropped from the spec?) and I've tried something (I forgot what I've tried exactly) as described on
https://github.com/bryanrsmith/aurelia-binding-loader
with:
<template>
<require from="styles.css!module!bind" as="styles"></require>
<div class.one-time="styles.first">First</div>
<div class.one-time="styles.second">Second</div>
</template>
which was very slow.
My knowledge about all this is very limited and I think it does a conversion from CSS to a JS object, after which the class of a tag are bound to the style in the JS object.
I thought it would make sense to to this conversion to JS at build time. So with my very limited gulp knowledge I changed process-css.ts in the following way:
import * as gulp from 'gulp';
import * as sourcemaps from 'gulp-sourcemaps';
import * as sass from 'gulp-sass';
import * as project from '../aurelia.json';
import { build } from 'aurelia-cli';
import * as path from "path";
import * as fs from "fs";
import * as rename from "gulp-rename";
import * as postcssmodules from "postcss-modules";
import * as postcss from "postcss"
import * as postcssJs from "postcss-js"
import * as tap from "gulp-tap";
export default function processCSS() {
return gulp.src(project.cssProcessor.source)
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(tap(handleCss))
.pipe(build.bundle())
};
function handleCss(cssFile, t) {
// get the path of the html file
var baseFilename = path.basename(cssFile.path, '.css');
var baseFilepath = path.join(path.dirname(cssFile.path), baseFilename);
var htmlFilepath = baseFilepath + '.html';
// check if the html file exists
if (fs.existsSync(htmlFilepath)) {
var root = postcss.parse(cssFile.contents.toString());
var cssAsJson = postcssJs.objectify(root);
var s = JSON.stringify(cssAsJson);
cssFile.contents = Buffer.from(s);
}
}
(adding handleCss).
This is not yet finished. The new object with the style has to be added to the bundle under the same name but WITH an extension ".js". How can I do this in a nice way?
It would be nice if this would work, but still it would be limited to scoped css classes, not css elements.
Another possibility I thought about is, maybe the component.scss styling can be inserted into the component.html (e.g. setting style properties of elements) during build time? If so, how could/should this be done? And are there any drawbacks from doing this?
Sorry if there are "dumb" questions in this post, basically this is all very new and it is difficult to find where to begin.
Thanks!

If you're using Aurelia with Webpack, you can use the ConventionDependenciesPlugin so that css/scss files are automatically included just like js and html. Once configured, you no longer need to require the stylesheets. Do note that you may have to restart Webpack watch if you add css/scss file after the html and js files, because ConventionDependenciesPlugin sometimes does not pick up the dependent file.

Related

import Css file from directory to inject in iframe head tag like <style> Vite + React JS

welcome to my ***** problem
I am spending some days trying to resolving something.
I am trying to create a webpage editor with Grapes JS, React JS and Vite everything was wonderful until the kingdom of creating different themes appears...
The themes are in different plugins, this plugins are in the project running from the react app, my problem is when i try to load a css file in the directory of the plugin :
import styles from "../../dist/main.css";
const cssStyle = document.createElement("style");
cssStyle.innerHTML = styles ;
const doc = iframe.contentDocument;
const f = setInterval(() => {
if (doc.readyState === "complete") {
doc.head.appendChild(cssStyle);
clearInterval(f);
}
}, 100);
This styles are apply globally in my react app and i only want to inject in a iframe, in the head tag.
Is any way to load a css file in react without compile globally this css file?
Thanks by the help
Vite automatically injects CSS styles into the page when you import a .css file. Quite helpful... until it's not. From what you describe I'm betting that is the culprit.
There is a way to disable that behavior: it looks like adding ?inline to the filename will disable the injection and just grab the file contents. So your first line would look like this:
import styles from "../../dist/main.css?inline";
That should give you styles as a pure string, and the rest of your code should then work.
P.S. Welcome to StackExchange :)

how to pass variable from main folder as property in module.css in React

In react project using module.css styling I want to make a main folder with variables commonly used for example file variable.js where I will have
export const colors = {
buttonBackground:"#FFFFFF"
}
I want to pass it to certain classes. Will it work if for example in list.module.css file I will write:
import {colors} from "..."
.complete {
background-color:${colors.buttonBackground}
}
Or it should be coded in different way ?
Sorry I don't have possibility now to test it on my own that's why I write and describe it.
thanks
regards
in case you need to use some js constants you can have a look at JSS which is a way to write css in js, you can integrate JSS in your react app using this guide

How do I use CSS Houdini in Next.js

I would like to use CSS Houdini in a Next.js project I am building. I have installed, via yarn, both the CSS Houdini package I want to use along with css-paint-polyfill. I am following the webpack instructions here https://houdini.how/usage
Here is my component:
import 'css-paint-polyfill';
import workletURL from 'url-loader!css-houdini-lines';
import styles from './Separator.module.css';
CSS.paintWorklet.addModule(workletURL);
export default function Separator() {
return <div className={styles.separator} />;
}
I am getting the dreaded
error - ReferenceError: window is not defined
at /home/tithos/code/web/new-tim/node_modules/css-paint-polyfill/dist/css-paint-polyfill.js:1:239
I tried putting the import for css-paint-polyfill in a useEffect, but the throw another error. I even tried const DynamicComponent = dynamic(() => import('../components/hello')) from https://nextjs.org/docs/advanced-features/dynamic-import, but I did not know how to reference the library.
Has any one solved this?
Seems like CSS Paint Polyfill eagerly accesses window, which means it will throw an error when in an environment which has no window, such as server phase of Next. There are multiple things you can do.
Modify your next.config.js to stub the aforementioned module when for Webpack when isServer is true. You can follow this page of the Next docs for this.
Create a dynamic component that's only imported on the client (I see you've tried this, but it should have worked, so maybe if you shared what you did in this regard, I could work out what's wrong with your approach).
Create an issue and send in a PR to the repository where the Polyfill is hosted to lazily access window depending on whether it's available or not.

Using css-loader without React

I'm building a small web app with Webpack-enabled CSS modules (via css-loader) and without React. My goal is to get the benefits of short, obfuscated CSS class names (as I'm currently using lengthy BEM class names) in my HTML by using the localIdentName: '[hash:base64:8]' option on css-loader. Since I'm not using React, I'm working with raw HTML that is not being programmatically generated through JSX file or document.write.
I've used css-loader with React plenty before, and it ultimately works because you're able to import the style class names in the React file and refer to them using the human-readable names, regardless of whatever the class name gets changed to by Webpack.
However, I'm confused how to deal with this when using raw HTML; I can't just import the styles in since it's not a JS file. If I have a class called photo__caption--large referenced in my HTML, and webpack converts the class name to d87sj, the CSS file will say d87sj but the HTML will still say photo__caption--large.
Is there some kind of loader for HTML files that's able to edit class names in the file to their Webpackified equivalents? Or should I really just be using React with CSS modules?
This github code might help you.
https://github.com/moorthy-g/css-module-for-raw-html
A bit of complicated setup needed. We need to wire the following packages together.
- postcss-loader
- postcss-modules
- posthtml-css-modules
- posthtml-loader
The following postcss configuration creates modules dump file (./tmp/module-data.json).
// postcss.config.js
module.exports = {
plugins: {
'postcss-modules': {
getJSON: function(cssFileName, json) {
const path = require('path'), fs = require('fs');
const moduleFile = path.resolve('./tmp/module-data.json');
const cssName = path.basename(cssFileName, '.css');
const moduleData = fs.existsSync(moduleFile) ? require(moduleFile) : {};
moduleData[cssName] = json;
fs.existsSync('./tmp') || fs.mkdirSync('./tmp');
fs.writeFileSync(moduleFile, JSON.stringify(moduleData));
},
generateScopedName: '[local]_[hash:base64:5]'
}
}
}
And the following webpack rule links html file to modules dump file.
{
test: /\.html$/,
use: [
{ loader: 'html-loader' },
{
loader: 'posthtml-loader',
options: {
plugins: [
require('posthtml-css-modules')('./tmp/module-data.json')
]
}
}
]
}
Finally, HTML uses css-module attribute instead of class
<div css-module="main.container">
<h2 css-module="main.title">Title for the page</h2>
</div>
Let me know if you have any issues
My understanding of Webpack, CSS Modules, & CSS-Loader is that the entire point is to use javascript to generate the files.
This enables all the name translation and what not. What's your goal with Webpack if you're writing static HTML?
There are several static site generators for Webpack that will allow you to get the result you want, BUT they're still building the HTML files.
Alternately you could look at tools similar to React (Vue or Angular) that allow you to write all your "templates" in straight HTML. In Vue for example, you can write only HTML (to be compiled from javascript) without needing to use any of its data binding or routing.

How could I make Aurelia include my styles as external styles via <link>?

I am trying to set up the conjunction of Atom editor, Sass, Typescript and Aurelia. This question is about Aurelia (installed via aurelia-cli) and its building system, I guess.
Well, I wrote style.sass for my component, then I required it in the component's view (app.html, for instance) as style.css. Fine, it works. But the content of compiled style.css gets included in index.html as internal styles, I mean everything goes inside <style>-tag, not through <link>. Also it seems that the corresponding .css file is never created at all. The stream just includes its content right in <style>-tag inside index.html.
How could I make Aurelia include my styles as external styles via <link>? In building task the last action is a build-plugin coming from aurelia-cli which is kinda black-box for me. Also aurelia.json is imported, so there should be a way to configure the needed behavior. A quick search didn't give me the answer, so here I am.
This is probably not the best solution, and not completely what you want, but perhaps it helps. You can do the following (I took a new TypeScript project):
First remove the css includes from your views.
Then, adjust the ./aurelia_project/tasks/process-css.ts task as follows:
import * as gulp from 'gulp';
import * as sourcemaps from 'gulp-sourcemaps';
import * as sass from 'gulp-sass';
import * as project from '../aurelia.json';
import {build} from 'aurelia-cli';
export default function processCSS() {
return gulp.src(project.cssProcessor.source)
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(project.platform.output));
};
This will output CSS files in the ./scripts folder. Then, adjust the aurelia_project/aurelia.json file as follows (remove css):
{
"name": "app-bundle.js",
"source": [
"[**/*.js]",
"**/*.{html}"
]
},
In your index.html you can now include the generated styles (or even in your components views).

Resources