craftkit encapsulates its CSS by ShadowDOM. So you can use simple CSS class name for your component.
And the CSS is defined by style()
instance method. So you can append definition to its super class.
This spec allows you to implement object oriented styling. Now the time to say goodbye to CSS name convention.
This post describes how to inherit style. In other words, how to share style sheet across Craft.UI.View in your application.
Style Method overriding
class Hello extends Craft.UI.View {
style(componentId){
return `
.root {
margin: 50px;
}
.text {
color: black;
}
`;
}
template(componentId){
return `
<div id="root" class="root">
<h1>Hello</h1>
<p class="text">World!</p>
</div>
`;
}
}
class HelloRed extends Hello {
style(componentId){
return super.style(componentId) + `
.text {
color: red;
}
`;
}
}
In HelloRed instance, margin:50px
is cascaded, and color:red
is applied as usual CSS rule.
class Aloha extends Craft.UI.View {
style(componentId){
return `
.root {
margin: 70px;
}
.text {
color: blue;
}
`;
}
template(componentId){
return `
<div id="root" class="root">
<h1>Aloha</h1>
<p class="text">World!</p>
</div>
`;
}
}
class AlohaRed extends Example {
style(componentId){
return super.style(componentId) + `
.text {
color: red;
}
`;
}
}
Hello
and Aloha
have same CSS class definition, but its instance can exist simultaneously without conflict.
Pseudo multiple inheritance
Craft.UI.View is also a plain JavaScript class. So you can't define multiple inheritance for you view class.
But style method is defined dynamically, and resolved by same principle of CSS. So you can implement pseudo multiple style inheritance something like this:
// file: HeaderStyling.js
export class HeaderStyling {
static css(){
return `
h1 { color:red; }
`;
}
}
//file: ParagraphStyling.js
export class ParagraphStyling {
static css(){
return `
p { line-height: 2em; }
`;
}
}
Import and load them in your style method.
import { HeaderStyling } from 'HeaderStyling.js';
import { ParagraphStyling } from 'ParagraphStyling.js';
class Hello extends Craft.UI.View {
style(componentId){
return HeaderStyling.css() + ParagraphStyling.css() + `
p { color: blue; }
`;
}
template(componentId){
return `
<div id="root" class="root">
<h1>Hello</h1>
<p>World!</p>
</div>
`;
}
}
Dynamic style injection
Above example imports style classes statically. Of course, it can be injected dynamically something like this:
class HelloController extends Craft.UI.View {
viewDidLoad(callback){
this.appendSubView(new Hello({
styles: [HeaderStyling,ParagraphStyling]
}))
}
}
class Hello extends Craft.UI.View {
constructor(options){
super(options);
this.injectedStyles = options.styles;
}
style(componentId){
return this.injectedStyles.map( css => css.css() ).join('') + `
p { color: blue; }
`;
}
template(componentId){
return `
<div id="root" class="root">
<h1>Hello</h1>
<p class="text">World!</p>
</div>
`;
}
}
Load external CSS
adoptedStyleSheets
is no yet supported by Safari. To load external CSS file from remote, at first you have to append it to header, and then append it to this.shadow.
var link = document.createElement('link');
link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css';
link.rel = 'stylesheet';
document.head.appendChild(link)
This is for console test. (You may preload in your index.html
)
Then, define view that is appending CSS to its this.shadow in constructor.
class Hello extends Craft.UI.View {
constructor(options){
super();
const link = document.createElement('link');
link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css';
link.rel = 'stylesheet';
this.shadow.appendChild(link);
}
template(componentId){
return `
<div id="root" class="root">
<h1>Hello</h1>
<i class="fas fa-globe"></i>
</div>
`;
}
}
NOTE
Above examples are runnable on playground.
var view = new Hello();
view.loadView();
Craft.Core.Context.getRootViewController().appendSubView(view);
🛺 Try CraftKit Playground:
https://github.com/craftkit/craftkit-playground
Top comments (0)