Using CSS3 attr() with transform rotate - css

I want to be able to rotate, in CSS via an attribute i.e.
<my-object data-angle="225"></my-object>
The CSS I have so far is
transform:rotate(attr(data-angle)deg);
But this throws an error, what is the correct syntax?

I'm not holding out any hope that they'll ever fully implement according to the standard that Asim points out, but the good news is that you can achieve nearly the same thing with Custom Properties aka CSS variables
There's a Javascript API for DOM elements to get and set these variables
el.style.setProperty('--foo', 'my custom property value')
or you can even set it directly in the HTML if you don't mind the inline style attribute:
<div style='--foo:"my custom prop val";'>
Here's an example (your mileage with this snippet may vary depending on your browser's support for custom properties):
:root {
--rotation: 5deg;
}
.rotate {
padding: 0.2em;
transition: transform .2s;
will-change: transform;
}
.rotate:hover {
transform: rotate(var(--rotation));
}
.more {
--rotation: 15deg;
}
<button class='rotate'>rotation</button>
<button class='rotate more'>more rotation</button>
<button class='rotate' style='--rotation: 30deg;'>yet more rotation</button>

That's not possible in current browsers out there. But the spec says:
The attr() CSS function is used to retrieve the value of an attribute
of the selected element and use it in the style sheet. It can be used
on pseudo-elements too and, in this case, the value of the attribute
on the pseudo-element's originated element is returned.
The attr() function can be used with any CSS property, but support for
properties other than content is experimental.
So it will be supported in near future.
Here's the MDN doc.

Related

Using attr to set css variable inline that work with CSP

I was thinking how I can use css variables without using inline styles. I thought that I can use this:
[data-color] {
--color: attr(data-color color, green);
}
* {
color: var(--color, blue);
}
<div data-color="red">hello</div>
It seems that attr work only in pseudo selectors (and probably only on content: property), but MDN attr page says:
The attr() CSS function is used to retrieve the value of an attribute of the selected element and use it in the stylesheet. It can also be used on pseudo-elements, in which case the value of the attribute on the pseudo-element's originating element is returned.
There is even demo but it don't work in Chrome on Linux, so it's of no use to me. It even don't work in Firefox on Linux.
Is there any other way to use css variables without inline styles and without writing dynamic <style></style> and nonce?
Not yet. In the same link you can read:
Note: The attr() function can be used with any CSS property, but support for properties other than content is experimental, and support for the type-or-unit parameter is sparse.
Still no browser support the attr() for properties different than content and also no support for the type-or-unit.
Worth to note that you can use attr() inside a CSS variable but it need to be later used with content. CSS variables is only an intermediate so we don't evaluate the support based on the variable but based on the property that will use the variable.
[data-color] {
--color: attr(data-color);
}
*::before {
content: var(--color, "default");
color:blue;
}
<div data-color="red">hello</div>
An interesting use of the CSS attr property, but as the question states, the support for it outside of the pseudo element property is sparse see for example https://developer.mozilla.org/en-US/docs/Web/CSS/attr
It's actually slightly worse than that because if you have:
* {
color: var(--color, blue);
}
[data-color] {
--color: green;
--color: attr(data-color);
}
<div data-color="red">hello</div>
similar to in the question but separated out to be more explicit. The --color: attr(data-color) does not flag a warning and get ignored and the green used. Instead it is accepted and --color set to the string. It's as if the browser sort of recognises the attr and that it should do something with it but doesn't actually do it fully.
For everyone who still want to manage CSS variable on HTML you can do it like that:
* {
color: var(--color, blue);
}
<div style="--color: red">hello</div>
<div>hello</div>

CSS non-standard "ZOOM" property

I have a css file with a class with zoom: 1.
I get the following error on the browser console.
This page uses the non-standard "zoom" property. Instead, you can use calc (), or "transform" together with "transform-origin: 0 0".
How do you convert the property from zoom to transform or calc?
ThankYou
You can find a description and recommendation on the MDN web docs:
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
recommendation:
The non-standard zoom CSS property can be used to control the magnification level of an element. transform: scale() should be used instead of this property, if possible. However, unlike CSS Transforms, zoom affects the layout size of the element.
demo:
div.t1 {
zoom: 0.5;
}
div.t2 {
transform:scale(0.5);
transform-origin: 0 0;
}
<div class="t1">Hello World</div>
<div class="t2">Hello World</div>

Can I trigger CSS transitions via selectors other than ":hover" and ":active"?

I'm learning about transitions in CSS3 via sololearn.com, where the only examples given for using transitions are in conjunction with the :hover selector.
Everything else I can find uses either that or :active with no explanation of what other selectors can be used or why selectors other than these two are not shown as examples.
Is there a way to start transitions without interaction from the user? Or would that require JavaScript?
tl;dr
You can use any selector to initiate a transition, but you don't really need one for it. All you need is to:
set the transition properties on the element
change the value of the property to be transitioned.
You can do both of the above without using CSS selectors, which are nothing more than a handy method available for setting DOM element properties.
initial answer
transitions work with any selector whatsoever. But they are not related to any selector and you don't really need selectors to perform CSS transitions.
All you need for a transition to work is to set the following transition properties:
transition-duration,
transition-delay,
transition-timing-function
transition-property. (has to be animatable for transition to work).
After this, whenever the property named in transition-property changes its value between two animatable values, the change between the initial and the set value happens according to the set transition properties.
This happens regardless of what exactly triggers the change of value for the transitioned property
It could:
change because a particular CSS selector (you defined) starts or stops applying (matching the element);
be changed directly using JavaScript.
Or, of course, by a combination of the two (i.e. use JavaScript to apply a class, which changes the value of the property being transitioned)
So, in effect, the answer to your question is: transitions work with any selector but they also work without one. They work based on DOM element property values, regardless of any selector.
A common way to demonstrate a transition is using :hover state because all one needs to do to switch between selectors (which is to control / demonstrate / observe the transition) is. well,... hover!
On:
For example is there a way to start transitions without interaction from the user?
Of course there is! A very basic example is to add a class on <body> when all page resources have finished loading.
When <body> element is created it doesn't have the class and when all resources have finished loading, the Window's onload event triggers. We can use this event to add the class. If a transition is properly defined on body and the transitioned property changes because a stronger selector now applies on the element, the transition will happen. Without any user interaction.
See it working:
window.onload = function() {
document.querySelector('body').classList.add('loaded')
}
body {
background-color: #fff;
transition: background-color 1s linear;
}
.loaded { background-color: #212121;}
You could also set a recursive function that toggles the state of an element and calls itself after a set amount of time, effectively toggling the state back after the set time, in a continuous cycle:
For the above example this would mean:
window.onload = toggleBodyClass;
function toggleBodyClass() {
document.querySelector('body').classList.toggle('loaded');
setTimeout(toggleBodyClass, 1234);
}
body {
background-color: #fff;
transition: background-color 1s linear;
}
.loaded { background-color: #212121;}
If the question is: "Can a selector start/stop applying without the use of JavaScript and/or user interaction?" It really translates to:
"Are there transitions triggered by something else than what usually triggers a transition?", with possible answers varying from:
"Why do you want to know?" to "Is there web browsing without JavaScript and/or user interaction?"
Transitions are, as Paulie_D says, changes in state. What this "state" refers to, is simply the value of any style property (that can be animated, anyway). Even the spec describes it the same way:
Normally when the value of a CSS property changes, the rendered result is instantly updated, with the affected elements immediately changing from the old property value to the new property value. This section describes a way to specify transitions using new CSS properties. These properties are used to animate smoothly from the old state to the new state over time.
This means that you don't actually need a selector to start transitions. Styles can be changed via CSS, JavaScript, or the inline style attribute. All of these are subject to transitions, because they all modify style property values. Selectors just happen to be the most common way of doing it because selectors and declaration blocks are the two fundamental components that make up style rules, themselves the building blocks of CSS.
Most other ways of using transitions with or without user interaction do in fact involve JavaScript because CSS doesn't support much state change without requiring user interaction (outside of animations, which are a different beast from transitions), but that doesn't mean that JavaScript is inherently required for transitions to work, because transitions are about state change, regardless of how that state change is invoked (JS or not).
Most tutorials use :hover and :active to demonstrate transitions simply because user interaction is the easiest and most intuitive way for readers to see transitions in action, and to learn what it means for an element to change state (albeit a different kind of state, but the principle is the same). It's also by far the most common use case for transitions: animating changes in state in response to user interaction.
But you don't actually need to change property values with a user interaction pseudo-class in order for transitions to work. You can change them with any selector, even if user interaction is handled by a different element (and that element doesn't have to start transitions using :hover or :active either)...
label {
transition: color 1s linear;
}
:checked + label {
color: #f00;
}
<p><input type=checkbox id=check><label for=check>Label</label>
... or by the page itself...
h1 {
transition: color 1s linear;
}
:target {
color: #f00;
}
<p><a href=#sec1>Section 1</a> <a href=#sec2>Section 2</a>
<h1 id=sec1>Section 1</h1>
<h1 id=sec2>Section 2</h1>
Once you add JavaScript into the mix, you can set property values directly (i.e. not use a selector)...
setTimeout(function() {
document.querySelector('p').style.color = '#f00';
}, 1000);
p {
transition: color 1s linear;
}
<p>Wait for it...
... change an element's class, ID or other attribute...
setTimeout(function() {
document.querySelector('p.foo').className = 'bar';
}, 1000);
setTimeout(function() {
document.getElementById('foo').id = 'bar';
}, 2000);
setTimeout(function() {
document.querySelector('p[data-attr]').dataset.attr = 'bar';
}, 3000);
p {
transition: color 1s linear;
}
p.bar { color: #f00; }
p#bar { color: #090; }
p[data-attr=bar] { color: #00f; }
<p class=foo>Wait for it...
<p id=foo>Wait for it...
<p data-attr=foo>Wait for it...
... or even move elements around in the DOM tree (although this does have limitations — notice that the Foo item fails to start its transition because it's getting detached before being reattached, while the Bar item is able to start its transition once it notices it's now first because it never leaves the DOM tree)...
setTimeout(function() {
var ul = document.querySelector('ul');
ul.appendChild(ul.firstChild);
}, 1000);
li {
transition: color 1s linear;
}
li:first-child { color: #f00; }
<ul><li>Foo<li>Bar</ul>
... and be able to start transitions all the same. Notice that all the JavaScript examples start transitions automatically, no user interaction required.
So, in conclusion, transitions are about state change, and said state change pertains to changes in style property values. These are independent of selectors or JavaScript, although selectors are a fundamental part of CSS and you do need JavaScript for most things.

How to remove a specific property in CSS engine?

I am making a Chrome extension and need to know if can do the following.
I want to remove a specific CSS properties like (filter, opacity, etc). The property must remain in the CSS or HTML, example: style="filter:blur(3px)", but this not should have any effect.
Well, if I understand correctly, you can use jQuery's .css() method (link). Here is an example:
CSS:
.box {
background-color: red;
}
JS:
$('.box').css('background-color', 'none');

input[type='text'] CSS selector does not apply to default-type text inputs?

The default input type is 'text'. I have always assumed then that CSS declarations targeting input[type='text'] would affect those inputs even if the type was not explicitly declared on the control. However, I just noticed that my default-type text inputs do not get the styles. Why is this the case? And how can I address this?
input[type='text'] {
background: red;
}
<input name='t1' type='text' /> /* Is Red */
<input name='t1' /> /* Is Not Red */
The CSS uses only the data in the DOM tree, which has little to do with how the renderer decides what to do with elements with missing attributes.
So either let the CSS reflect the HTML
input:not([type]), input[type="text"]
{
background:red;
}
or make the HTML explicit.
<input name='t1' type='text'/> /* Is Not Red */
If it didn't do that, you'd never be able to distinguish between
element { ...properties... }
and
element[attr] { ...properties... }
because all attributes would always be defined on all elements. (For example, table always has a border attribute, with 0 for a default.)
Because, it is not supposed to do that.
input[type=text] { } is an attribute selector, and will only select those element, with the matching attribute.
By CSS specifications, browsers may or may not use information about default attributes; mostly the don’t. The relevant clause in the CSS 2.1 spec is 5.8.2 Default attribute values in DTDs. In CSS 3 Selectors, it’s clause 6.3.4, with the same name. It recommends: “Selectors should be designed so that they work whether or not the default values are included in the document tree.”
It is generally best to explicitly specify essential attributes such as type=text instead of defaulting them. The reason is that there is no simple reliable way to refer to the input elements with defaulted type attribute.
To be compliant with all browsers you should always declare the input type.
Some browsers will assume default type as 'text', but this isn't a good practice.
try this
input[type='text']
{
background:red !important;
}

Resources