I have a Gwt widget library with configuration property:
<set-configuration-property name="CssResource.style" value="stable-notype"/>
which is expected to leave original css names, then a css file (example)
.invader {
width: 400px;
height: 400px;
background-color: #DBDBDB;
}
.invader .button {
background-image: url('merged.png');
width: 64px;
height: 64px;
background-position: 0px 64px;
background-color: #BA6622;
}
after that, a generated css resource
interface WidgetStyle extends CssResource {
String button();
String invader();
}
And when I call ensureInjected() on WidgetStyle instance (and/or) use styles programatically/in ui:binder with e.g.
<ui:style src="WidgetStyle.css" field="style" />
<g:HTMLPanel styleName="{style.invader}" ui:field="panel" />
Then, in result html file in browser instead of one injected css styles i got four defined selectors:
.org-invader-widget-client-WidgetStyle-invader;
.org-invader-widget-client-WidgetStyle-invader .org-invader-widget-client-WidgetStyle-button;
.org-invader-widget-client-MyWidget_UIImpl_GenCss_style-invader;
.org-invader-widget-client-MyWidget_UIImpl_GenCss_style-invader .org-invader-widget-client-MyWidget_UIImpl_GenCss_style-button;
Those pairs duplicate the styles above just with different names. I see that the second pair come as "MyWidget owned" styles, but how can I force all application to use only those css classes i defined in a .css file without any obfuscation?
Futhermore, the second pair of css-classess fails to apply properly. Only the first is applied, second is not matched.
What I did wrong here?
Ok, i found that accessing css with
<ui:style ... />
injects styles and css classes might get extra prefix, proper way for me was to access styles by a ClientBundle with
<ui:with ... >
Obfuscation overriding does not work 'by default' in SuperDevMode in *.gwt.xml and, if I am right, it has to be configured with DevMode run parameter.
Related
I'm currently developing a web application in Outsystems in which I have the need to customize the CSS, in which I'm using variables. I need to guarantee the app works cross-browser, including in Internet Explorer. IE doesn't support CSS variables, as you can see in the picture below from this source.
Since I have to use CSS variables, is there any workaround for the usage of variables in IE?
Yes there is a way, the same way you make any css compatible: use a specific css fallback that is supported by the browser.
body {
--text-color: red;
}
body {
color: red; /* default supported fallback style */
color: var(--text-color); /* will not be used by any browser that doesn't support it, and will default to the previous fallback */
}
This solution is incredibly redundant and 'almost' defeats the purpose of css variables....BUT it is necessary for browser compatibility. Doing this would essentially make the css variables useless but I implore you to still use them because it will serve as an important reminder to the fact that these values are referenced elsewhere and need to be updated in all cases, otherwise you forget to update every related occurrence of 'color' and then you have inconsistent styling because relevant css values are out of sync. The variable will serve more as a comment but a very important one.
There is a polyfill, which enables almost complete support for CSS variables in IE11:
https://github.com/nuxodin/ie11CustomProperties
(i am the author)
The script makes use of the fact that IE has minimal custom properties support where properties can be defined and read out with the cascade in mind.
.myEl {-ie-test:'aaa'} // only one dash allowed! "-"
then read it in javascript:
getComputedStyle( querySelector('.myEl') )['-ie-test']
From the README:
Features
handles dynamic added html-content
handles dynamic added , -elements
chaining --bar:var(--foo)
fallback var(--color, blue)
:focus, :target, :hover
js-integration:
style.setProperty('--x','y')
style.getPropertyValue('--x')
getComputedStyle(el).getPropertyValue('--inherited')
Inline styles: <div ie-style="--color:blue"...
cascade works
inheritance works
under 3k (min+gzip) and dependency-free
Demo:
https://rawcdn.githack.com/nuxodin/ie11CustomProperties/b851ec2b6b8e336a78857b570d9c12a8526c9a91/test.html
In case someone comes across this, has a similar issue where I had it set like this.
a {
background: var(--new-color);
border-radius: 50%;
}
I added the background colour before the variable so if that didn't load it fell back on the hex.
a {
background: #3279B8;
background: var(--new-color);
border-radius: 50%;
}
Yes, so long as you're processing root-level custom properties (IE9+).
GitHub: https://github.com/jhildenbiddle/css-vars-ponyfill
NPM: https://www.npmjs.com/package/css-vars-ponyfill
Demo: https://codepen.io/jhildenbiddle/pen/ZxYJrR
From the README:
Features
Client-side transformation of CSS custom properties to static values
Live updates of runtime values in both modern and legacy browsers
Transforms <link>, <style>, and #import CSS
Transforms relative url() paths to absolute URLs
Supports chained and nested var() functions
Supports var() function fallback values
Supports web components / shadow DOM CSS
Watch mode auto-updates on <link> and <style> changes
UMD and ES6 module available
TypeScript definitions included
Lightweight (6k min+gzip) and dependency-free
Limitations
Custom property support is limited to :root and :host declarations
The use of var() is limited to property values (per W3C specification)
Here are a few examples of what the library can handle:
Root-level custom properties
:root {
--a: red;
}
p {
color: var(--a);
}
Chained custom properties
:root {
--a: var(--b);
--b: var(--c);
--c: red;
}
p {
color: var(--a);
}
Nested custom properties
:root {
--a: 1em;
--b: 2;
}
p {
font-size: calc(var(--a) * var(--b));
}
Fallback values
p {
font-size: var(--a, 1rem);
color: var(--b, var(--c, var(--d, red)));
}
Transforms <link>, <style>, and #import CSS
<link rel="stylesheet" href="/absolute/path/to/style.css">
<link rel="stylesheet" href="../relative/path/to/style.css">
<style>
#import "/absolute/path/to/style.css";
#import "../relative/path/to/style.css";
</style>
Transforms web components / shadow DOM
<custom-element>
#shadow-root
<style>
.my-custom-element {
color: var(--test-color);
}
</style>
<div class="my-custom-element">Hello.</div>
</custom-element>
For the sake of completeness: w3c specs
Hope this helps.
(Shameless self-promotion: Check)
Make a seperate .css file for your variables. Copy/paste the contents of the variable.css file to the end of your main.css file. Find and replace all the variable names in the main.css file to the hex code for those variables. For example: ctrl-h to find var(--myWhiteVariable) and replace with #111111.
Side note: if you keep the :root{ } in the main.css file and just comment it out, you can use that to track those hex codes later if you want to update your fallback colors.
Another way to do it is declaring colors in a JS file (in my case I'm using react) and then just use the variable you defined in the JS file.
For example:
in globals.js
export const COLORS = {
yellow: '#F4B400',
yellowLight: '#F4C849',
purple: '#7237CC',
purple1: '#A374EB',
}
in your file
import { COLORS } from 'globals'
and then just use COLORS.yellow, COLORS.purple, etc.
body {
--text-color : red; /* --text-color 정의 */
}
body {
color: var(--text-color, red); /* --text-color 정의되지 않으면 red로 대체됨 */
}
body {
color: var(--text-color, var(--text-color-other, blue));
/* --text-color, --text-color-other 가 정의되지 않으면 blue로 대체됨 */
}
There is no way yet in "normal" css but take a look at sass/scss or less.
here is a scss example
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
I recommend setting your css variables as sass variables, then using sass interpolation to render the color in your elements.
:root {
--text-color: #123456;
}
$text-color: var(--text-color);
body {
color: #{$text-color};
}
If im not wrong there is a workaround, the CSS #ID Selector. Which should work for IE > 6 I guess.. So you can
.one { };
<div class="one">
should work as
#one {};
<div id="one">
I am using css modules, however a library I use in a component to append tweets with JavaScript adds some elements to my component in the following structure:
<div class='user'></div>
<div class='tweet'></div>
I want to now style these elements in my css module for the component, as follows:
MyComponent.css
.user {
/* styles */
}
.tweet {
/* styles */
}
However of course now my .user class changes to .MyComponent__user___HZWfM due to the hash naming in the webpack loader.
How can I set a global style in my css module?
According to the css modules docs, :global switches to the global scope for the current selector. e.g.
:global(.example-classname)
So this should work:
:global(.tweet) {
text-align: left;
}
:global(.user) {
text-align: left;
}
Or define a global block
:global {
.tweet {
text-align: left;
}
.user {
text-align: left;
}
}
Can use module class with static class with this way.
myStyle.module.css
.moduleClass_g1m59k:global(.StaticClass) {
background-color: orange;
}
Output will generate like this
.moduleClass_g1m59k.StaticClass {
background-color: orange;
}
Many people have struggled with this and there doesn't seem to be any one agreed upon solution. The one I have settled with involves some tweaking of your bundler and specifically addresses the need to import libraries as-is without having to wrap them or edit them manually.
In my webpack config I have set it to scan all files ending css except those within the 'node_modules' and 'src/static' folders. I import my libraries from here and they dont suffer the classname transforms so I am free to use regular classnames for global css and the className={styles.element} convention as usual for modular css (which will compile down to .component_element__1a2b3 or something similar).
Here is an example of a working production webpack config with this solution:
http://pastebin.com/w56FeDQA
I know that sass provides us with #extend method that allows me to do this:
%knob {
width: 10px;
height: 10px;
}
.house {
&__door {
&__knob {
color: inherit;
#extend %knob;
&--red {
#extend %knob;
// $1
color: red;
}
&--blue{
#extend %knob;
// $1
color: blue;
}
}
}
}
however i would prefer not to define abstract class %knob at all, would it be possible to reference/include properties defined in __knob (width and height in this case) from within its modifiers --red and --blue?
im including sassmeister snippet here to help out a bit: http://sassmeister.com/gist/58b5b4673a18ecadbba7
example here might not look like an issue but if an element with a long class name has 2 or more different groups of modifiers, and I wont create an abstract class, i sometimes end up with html tags looking like this <p class="some other classes some-house__some-door__some-knob some-house__some-door__some-knob--red">example</p> which I find not very desirable.
what i would like to achieve:
referencing parent element would alow me to reduce this string to <p class="some other classes some-house__some-door__some-knob--red"></p> without necessity of declaring an abstract %knob class
why am I hesitant about using an abstract class here:
declaring an abstract class inside __door element (http://sassmeister.com/gist/bc49e0885342e96a8fbd) gives me this result:
.house__door .house__door__knob, .house__door .house__door__knob--red, .house__door .house__door__knob--blue {
width: 10px;
height: 10px;
}
instead of desired
.house__door__knob, .house__door__knob--red, .house__door__knob--blue {
width: 10px;
height: 10px;
}
and declaring an abstract class outside of the scope its going to be used in makes the code less readable
or maybe theres a different apporach i could use in order to make my code more readable/maintainable?
while searching for an answer to my question i came to the conclusion that inheriting parent element properties/ using #extend or #include here might not be the best idea as it would work well only if an element had 1 modification at most:
in other cases if multiple modifications extended same model, and were to be used to the same html element, all of the base properties would be declared multiple times
also there is no need at all to deeply nest elements (i.e. foo__bar__baz). separating elements makes code easier to maintain.
I'm looking into LESS because I definitely see some of their benefits. For instance colour declaration.
One thing I don't understand tho, and maybe I'm not getting the flow right is - why use the following LESS snippet
.radius {
-webkit-border-radius:5px;
-moz-border-radius:5px;
border-radius:5px;
}
.btn-red{
background-color:red;
.radius;
}
.btn-green{
background-color:green;
.radius;
}
...
When we can use the .radius class in the html file right away. I'm left with the impression that LESS will add a ton of duplicate code once it gets compiled.
I'm using the following, which makes more sense. Same with font-size, margins, etc... Aren't classes used in such cases?
<div class="btn-red radius">Cancel</div>
<div class="btn-green radius">Go</div>
The snippet above does not benefit from SASS/LESS capabilities that much. Lets have a closer look and check this SCSS snippet.
// Abstract placeholder.
%radius {
border-radius: 5px;
}
// Put your global styling here.
// I'm assuming that you can alter the markup and have button.btn.btn-green
.btn {
// Color modifier.
&-red {
#extend %radius;
background-color: red;
}
&-green {
#extend %radius;
background-color: green;
}
}
The CSS output will be:
.btn-red, .btn-green {
border-radius: 5px;
}
.btn-red {
background-color: red;
}
.btn-green {
background-color: green;
}
And then you have to pick up Autoprefixer and vendor-prefixes issue is solved once and for all.
Because now, you can just specify the class btn_red or btn_green and all the buttons will automatically have a radius.
Your HTML should contain only the semantics, and styling or classes referring to styling should not be part of it.
That applies to the other classes as well. If for instance, you would rename btn_red to btn_cancel, you have a meaningful classname that you can apply to any kind of cancel button. And in the CSS you can specify that a cancel button is red and a 'Go' button is green, and both have a radius, without needing to modify the HTML at all.
So, the ultimate goal is to have the HTML describe the structure and the CSS describe how that structure should look. And a CSS preprocessor is only their to make a bulky spaghetti-like CSS file more structured.
There are several benefits.
You can use more semantic class names. Rather than encoding style information directly in your class names, (btn-red, radius) you could use a single class that conveys the usage of the style, rather than its contents.
You can avoid repeating yourself.
#radius-size: 5px;
-webkit-border-radius:#radius-size;
-moz-border-radius:#radius-size;
border-radius:#radius-size;
You can parameterize it so that you'd be able to use different radiuses (radii?) in different contexts.
.radius(#radius-size) { ... }
Because there are cases that developer has-no-access or don't-want to change the markup. and the only solution is to include all props from a predefined class.
for example:
you have bootstrap loaded (then you already have .has-success and .has-error classes) and if you want to use HTML5's native form validation using input's :valid and :invalid states, you have to use JavaScript to add/remove success/error classes based on input's states. but with this feature of LESS you can include all props of success/error class inside input's states. the code for this example could be something like this:
#myinput {
&:valid { .has-success; }
&:invalid { .has-error; }
}
Using GWT 2.1, I am trying to create a CSS file that contains numerous constants and common styles. I would like to use the ui:style tag to include it in the UiBinder template:
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
<ui:style field="css" src="constants.css" />
</ui:UiBinder>
I can easily utilize the styles for elements:
<g:FlowPanel styleName="{css.panel}">...</g:FlowPanel>
But attempting to use the constants in another Style block fails:
<ui:Style>
.templateSpecificStyle {
background-color: {css.royalBlue};
padding: 1em;
}
</ui:Style>
Oddly I do not receive a compile error. The obfuscated CSS class is created; however, the content is empty. Is there any way to access these CSS constants within another Style block? Is it possible using the older ResourceBundle / CssResource pattern?
After re-reading https://stackoverflow.com/questions/3533211/need-app-wide-css-constants-in-gwt/4143017#4143017 I see that the constants work if you add the template specific style within the style block:
<ui:Style src="constants.css">
.templateSpecificStyle {
background-color: royalBlue;
padding: 1em;
}
</ui:Style>
This is perfect for my needs.
It may be in your best interest to define these constants in some class, then use runtime substitution to include this constant in each CSS resource you intend to use.
CSSConstants.java
package com.foo.client;
public final class CSSConstants {
public static final String ROYAL_BLUE = "#4169E1";
}
Style block in UiBinder template
<ui:style>
#eval royalBlue com.foo.client.ROYAL_BLUE
.templateSpecificStyle {
background-color: royalBlue
}
</ui:style>
Note that even the name of the technique is "runtime substitution", the GWT compiler will replace royalBlue with a string literal because the value of royalBlue can be evaluated at compile time.
For more cool stuff that you can do in CSS resources, take a look at http://code.google.com/webtoolkit/doc/latest/DevGuideClientBundle.html#CssResource