I tried to declare some embedded css with Binding.scala
import com.thoughtworks.binding._, Binding._
import org.scalajs.dom._
#dom def css = <style>
body {
background-color: lightblue;
}
</style>
dom.render(document.head, css)
However, I got the error message:
ScalaFiddle.scala:6: error: not found: type lightblue
background-color: lightblue;
^
ScalaFiddle.scala:6: error: not found: value background
background-color: lightblue;
^
ScalaFiddle.scala:6: error: not found: value color
background-color: lightblue;
^
How can I fix it?
You see the error message because { is a special character in Scala's XML literal.
Use a CDATA section in the style element.
#dom def css = <style>
<![CDATA[
body {
background-color: lightblue;
}
]]>
</style>
The { does not have special meaning in the CDATA section any more.
Note this CDATA approach only works when coalescing flag is on.
See https://github.com/ThoughtWorksInc/Binding.scala/issues/30 and https://github.com/ThoughtWorksInc/Binding.scala/issues/58 if you accidentally turns the flag off.
Using the answer of Yang Bo:
#dom def css = <style>
<![CDATA[
body {
background-color: lightblue;
}
]]>
</style>
Gives me an Exception:
ScalaFiddle.scala:22: error: overloaded method value domBindingSeq with alternatives:
( text: String)binding.this.Binding.Constants[raw.this.Text]
...
See https://scalafiddle.io/sf/ATMVpjV/0
This solved it:
#dom def css = <style>
{"""
body {
background-color: lightblue;
}
"""
}
</style>
See https://scalafiddle.io/sf/ATMVpjV/1
Related
I have HTML table in Angular web app.
Get the data from the database via service and display it as text.
One of the columns is Status, so I need to present that variable not as text,
but as a circle of certain color, so if that cell value is "green",
it should show as green circle.
Here is what I have.
CSS (part of Component Styles):
:host ::ng-deep td.circle {
text-align: center;
font-size: 0;
background-color: RED; <--- need to pass param here
}
I define that column as:
.circle {
border-radius: 50%;
height: 24px;
width: 24px;
}
HTML:
<app-table [attrs]="serviceapi" [monthSelected]="monthSelected" ></app-table>
TS for that table:
In constructor:
this.data = {
headers: [],
rows: []
};
ngOnInit() {
this.tableMetricsService.getTableMetrics(
JSON.parse(this.attrs).api,
this.monthSelected
).subscribe(response => {
this.data = response;
}
);
}
Any idea how to "translate" cell value into the CSS background-color ?
TIA,
Oleg.
You could put a data attribute on the html and write a corresponding selector:
[data-status="green"] {
background: green;
}
[data-status="red"] {
background: red;
}
<div data-status="green">Green</div>
<div data-status="red">Red</div>
But I don't see any advantage to this approach over using a regular css class:
.green {
background: green;
}
.red {
background: red;
}
<div class="green">Green</div>
<div class="red">Red</div>
Here is what worked for me:
<div *ngIf="cell.styleClass == 'circle'" [ngStyle]="{'background-color': cell.value}" [ngClass]="cell.styleClass">
</div>
Is it possible to use pure CSS variables with Vue without having to link any stylesheets or use SASS/PostCSS? Unsure why I'm unable to get this to work in its most basic form.
<template>
<div id="test">
TEST
</div>
</template>
<style scoped>
:root {
--var-txt-color: #c1d32f;
}
#test {
color: var(--var-txt-color);
}
</style>
I know you highlighted "without having to link any stylesheet", but I run into the same issue and there is a simple option - use just one external css file and include it in your App.vue, then you can access the variables anywhere else, in scoped styles as well.
variables.css
:root {
--font-family: "Roboto", "Helvetica", "Arial", sans-serif;
--primary-color: #333a4b;
}
App.vue
<style>
#import './assets/styles/variables.css';
</style>
LandingView.vue
<style scoped>
#landing-view {
font-family: var(--font-family);
font-weight: 300;
line-height: 1.5em;
color: var(--primary-color);
}
</style>
This won't work as expected because of scoped attribute for stylesheet. Example above compiles into:
[data-v-4cc5a608]:root {
--var-txt-color: #f00;
}
And, as you understand, it will not target actual :root element.
It can be solved by:
Not using scoped attribute for this stylesheet. Notice that it may cause styles conflict with other variables declarations for :root element.
Using current component's wrapping element as root. If we declare variables this way:
.test {
--var-txt-color: #c1d32f;
color: var(--var-txt-color);
}
.test-child-node {
background-color: var(--var-txt-color);
}
Then it will can reuse variables for other elements of the same component. But still, it won't be possible to use declared variables inside child components without removing scoped, if it is the case.
Why not just use this?
<style scoped>
* {
--var-txt-color: #c1d32f;
}
</style>
The generated CSS is:
*[data-v-d235d782] {
--var-txt-color: #c1d32f;
}
This has been working for me.
I just discovered that it looks like this also works, using the "deep selector"
>>> {
--var-txt-color: #c1d32f;
}
Generated CSS is:
[data-v-d235d782] {
--var-txt-color: #c1d32f;
}
I think I like this method more.
One workaround is to define them under a non-scoped style element like the following. However one thing to note here is, these variables will be exposed to other Vue components as well.
<style>
:root {
--var-txt-color: #c1d32f;
}
</style>
<style scoped>
#test {
color: var(--var-txt-color);
}
</style>
Late answer - Here is a working example with css vars derived from standard vue structures.
<template>
<div>
<component :is="'style'">
:root {
--color: {{ color }};
--text-decoration: {{ textDecoration }};
--font-size: {{ fontSize }};
}
</component>
<p>example</p>
</div>
</template>
<script>
export default {
props:{
color: {
type: String,
default: '#990000'
}
},
data: function () {
return {
textDecoration: 'underline'
}
},
computed: {
fontSize: function (){
return Math.round(Math.random() * (5 - 1) + 1) + 'em';
}
}
}
</script>
<style>
p{
color: var(--color);
text-decoration: var(--text-decoration);
font-size: var(--font-size);
}
</style>
Starting from the top...
Vue must have 1 root element, so I needed a div tag in order to include a sample p tag. However, you can just use the component-is-style tag and get rid of the div and p tags. Note the need for extra quotations "'style'".
The normal vue style tag can be scoped or not - as needed.
Well, now you can use CSS variable injection.
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
font: {
weight: '800'
}
}
}
}
</script>
<style>
.text {
color: v-bind(color);
font-weight: v-bind('font.weight');
}
</style>
Those styles are also both reactive and scoped. There won't be any unintended inheritance issues. Vue manages the CSS variables for you.
You can take a look at the RFC here.
I want to import my stylesheet with variable inside :
<dom-module id="colors-palette">
<template>
<style>
:host {
--dark-gray: #263238;
--light-gray: #e6ebed;
--light-blue: #00bcd4;
--autovision-blue: #174291;
--background-box-number-applications: red;
--color-box-number-applications: orange;
}
</style>
</template>
</dom-module>
I want to do it dynamically. My folder structure is :
-themes
-theme1
-style.html
-theme2
-style.html
-theme3
-style.html
I detect the theme when my-app is ready and after that I try to import my style like this in the ready function :
Polymer.importHref(this.resolveUrl('../themes/' + this.getCurrentTheme() + '/colors-palette.html'));
The file is loaded but the var in the style in my-app.html doesn't change :
app-header {
background-color: var(--dark-gray);
}
And I've got this error in the console :
Could not find style data in module named colors-palette
Any idea ? Or maybe I have to do otherwise ?
Thanks a lot
Your colors-palette.html should just contain the styles setting it globally for html.
<custom-style>
<style is="custom-style">
html {
--dark-gray: #263238;
--light-gray: #e6ebed;
--light-blue: #00bcd4;
--autovision-blue: #174291;
--background-box-number-applications: red;
--color-box-number-applications: orange;
}
</style>
</custom-style>
Is there any contraindications on stylizing Angular2 custom element directly and selecting them with CSS selector ?
Example :
// HTML
<My-Page>
<header></header>
<main></main>
<My-Footer class="sticky-footer"></My-Footer>
</My-Page>
// CSS
My-Page {
background-color: grey;
}
header {
...
}
.sticky-footer {
position: absolute;
}
Good or bad practice ?
While this is perfectly valid it breaks modularity. A component can style its own root-element:
my-page.component.css
:host{
background-color: grey;
}
header {
...
}
.sticky-footer {
position: absolute;
}
This will achieve the same thing and contains CSS that's vital to your MyPageComponent in the component.
You should use piercing CSS combinators >>>, /deep/ and ::shadow
styles: [
`
:host { background-color: grey; }
:host >>> header{
background:yellow;
}
:host >>> My-Footer{
position: absolute;
}
`
],
template:
`
<My-Page> //<----no need as this becomes your :host
<header></header>
<main></main>
<My-Footer class="sticky-footer"></My-Footer>
</My-Page> //<----no need
`
I have a variable which have empty string as default value and it can be changed dynamically based on skin name. So I tried to write my sass selector like this.
default.scss:
$skin: '';
green.scss:
$skin: 'green';
main.scss:
#import 'default.scss';
.#{$skin} .header{
color: black;
}
So I expected the below output from generated CSS.
.header{
color: black;
}
and
.green .header{
color: black;
}
But it throws below error while compiling
Invalid CSS after ".": expected class name, was ".header"
You could use a function for this:
$skin: 'green';
#function skin(){
#if $skin != '' { #return '.' + $skin + ' '; }
#else { #return ''; }
}
Now you could use it like this:
#{skin()} .header { ... }
Which will output:
.green .header { display: block; }
It might be better to use a better global variable name (skin seems like something that might quickly be reused - I would suggest something like $global-skin-name or something, but thats just semantics).