What is the alternative to :dir() in Chrome? - html

I would like to know how we can implement this code to work in chrome browser,
/* Selects any element with right-to-left text */
:dir(rtl) {
background-color: red;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/:dir
what is the alternative in Chrome Browser?

Since you're using the dir HTML attribute, you can use a CSS attribute selector to style that element accordingly. In case it is not obvious, this is not the same thing as the :dir() pseudo-class in CSS. Attribute selectors are widely supported across all modern browsers.
For Chrome, you may need to apply the element to the <body> instead, or be prepared to use body { background-color: inherit; }:
html[dir="rtl"] {
background-color: red;
}
body {
background-color: inherit; /* Required for Chrome */
}
<html dir="rtl">
<body>
<div>A red document background</div>
</body>
</html>
You don't have to apply it to the whole document either, of course. You can apply it to a specific element only:
div[dir="rtl"] {
background-color: red;
}
<html>
<body>
<div>A white background</div>
<div dir="rtl">A red background</div>
</body>
</html>
If you would like to use JavaScript to detect the dir attribute, you can do so this way (or Google for your favorite way to detect an element via JS... there are at least half a dozen different ways):
/* EcmaScript 6 required, which shouldn't be an issue for modern Chrome, Firefox, Edge, etc. */
const doc = document.querySelector('html');
if (doc.hasAttribute('dir')) {
const textDir = doc.getAttribute('dir');
if (textDir == 'rtl') {
doc.classList.add('rtl');
} else {
doc.classList.add('ltr');
}
}
.rtl {
background-color: red;
}
body {
background-color: inherit; /* again, only needed for Chrome */
}
.ltr {
/* whatever styles you want for LTR text direction */
background-color: green;
}
<html dir="rtl">
<body>
<div>A red document background</div>
</body>
</html>

:dir() is indeed very useful since it refers to the direction of the element even if inherited from the parent or ancestor, but unfouruntately it's only supported in Firefox as you mentioned.
[dir="rtl"] is supported cross-browser, but it only refers to elements that have this specifically. If the entire document is one direction and it is specified in either the <html> or <body> tag, then that's not a big problem since you can simply use the descendant selector. For example
[dir="rtl"] p {
background: red;
}
However, this becomes complicated in a bidirectional document with nested sections. For example
<body dir="rtl">
<p>עברית (RTL text)</p>
<div dir="ltr">
<p>English (LTR text)</p>
<div dir="rtl">
<p>עברית (another RTL text)</p>
</div>
</div>
</body>
Sure, you can apply style rules to both directions like this
[dir="ltr"] p {
background: green;
}
[dir="rtl"] p {
background: red;
}
but CSS does not care which ancestor is closer, so the code above would still apply red to all paragraphs (and even reversing the order of rules wouldn't help for the nested section).
What you can do in this case is using CSS variables, which are inherited. For example
[dir="ltr"] {
--p-background: green;
}
[dir="rtl"] {
--p-background: red;
}
p {
background: var(--p-background);
}
In this case the variable is applied directly to the element with the specified direction, then the variable value is inherited through the element chain the same way the direction itself does, and affects the styling of the element defined to use the variable value - in this example the <p> element.

Related

Why "all: initial" makes <style> tag visible? And how do I reset everything to initial state in css?

I'm making a plugin that dynamically generates a container on any page.
Because there might be some predefined rules that change the appearance of the contents inside my .my-plugin, so I set
.my-plugin * {
all: inital;
}
to the <style> tag inside of it.
But somehow it makes the <style> tag visible:
/* The style that from the page, which is uncertain */
h1 {
color: red;
}
<h1>This is red</h1>
<!-- dynamically injected code -->
<div class="my-plugin">
<style>
.my-plugin * {
/* reset everything to default state */
all: initial;
}
.my-plugin {
border: solid 1px black;
}
</style>
<h1>This is not red</h1>
</div>
How do I set everything inside a tag back to their initial states?
I know I can do something like .my-plugin style { display: none; }, but what about other tags that should not be invisible as well?
Ultimately I just don't want the h1 inside .my-plugin to be red.
Is there a better approach?
initial for display is inline for all elements which obviously includes style elements. This overrides the display:none style applied by the user-agent style sheet.
To get the styles as they were before the author styles start being applied, what you really want is { all: revert; } but the browser compatibility is not good yet.

CSS :not selector being ignored

So I have a div with class='content' and inside that, another div with attribute style='background-color:#FF0000' so my code looks like the following:
<div class='content'>
Here is some text outside the red background div
<div style='background-color:#FF0000'>
Here is some text inside the red background div
</div>
</div>
And in my stylesheet I have the following:
[style^='background'] {
color:#00FF00
}
This works and I get green text inside the red background. However:
:not([style^='background']) {
color:#00FF00
}
This still makes the red background text green, along with everything else in the document. I have tried the following:
div:not([style^='background']) {
color:#00FF00
}
.content :not([style^='background']) {
color:#00FF00
}
:not([style]) {
color:#00FF00
}
Yet all of these make the red-background text green, when clearly I have the :not selector.
However, I have elsewhere:
.content div:not([style^='text-align']) {
color:#1f1f1f;
}
.content div :not(span[style^='font-size: 150%']) {
color:#EEE;
}
And these work just fine.
So I don't understand why the red background div won't work at all and is selected by the :not selector?
Example:
:not(.content) {
color:#FF0000
}
<div class='content'>
Here is some text that shouldn't be red
</div>
color is an inherited property. So if your element has no color set, it inherits the color from the next ancestor element that has a color defined. In your example,
:not(.content) { color: #F00; }
this also targets the body element, so your div.content inherits color: #F00;.
To avoid this, specify inherited properties on the elements you don't want inheritance on.
.content { color: green; }
:not(.content) {
color: red;
}
<div class="content">
Here is some text that shouldn't be red
</div>
Quirks, tricks, and unexpected results of :not
:not(.foo) will match anything that isn't .foo, including <html> and <body>.
You need to increase specificity to avoid this, e.g. div:not(.content).
In addition:
div:not([style^='background']) {
/* also targets parent divs */
color: #00FF00;
}
.content :not([style^='background']) {
/* You have a space here - this targets _children_ of .content
that are :not([style^='background']. Is this what you want? */
color: #00FF00;
}
Remember that the "C" in "CSS" stands for cascading, and one aspect of that is inherited styles. Many styles (such as color) affect children of matched elements too, not just the element itself.

How to enforce css style over existing classes (specially in Bootrstap)

When I want to apply a certain style to a div (specially using bootstrap 3), I create my own class like this:
.myClass {
width: 30%;
padding-right: 0px;
}
<div class="myClass"></div>
But sometimes the div style is overwritten by the bootstrap classes or another inherited properties (I don't understand completely the inheritance in CSS3), but if I apply directly in the div:
<div style="width: 30%;padding-right: 0px;"></div>
2 ways to force CSS on an element in this case :
You have you custom CSS located in a local .css file : put the <link> tag for this custom stylesheet after the Bootstrap css file.
Set the CSS rule !important after each properties so they will get an extra authority upon others
CSS inheritance
.myClass is less than div.myClass which is less than body div.myClass.
The Bootstrap is using usually more than one identifier. Like .ourClass.theirClass.yourClass which is hard to overwrite. Inspect your element in your browser to see the inheritance and try to overwrite it the css way before using any !important attributes.
The last rule defining a style of the element will be aplied to it.
So if you have various stylesheets in your page, the order of the files should be in the order you want them to be applied. example:
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="secondStyle.css">
Every style rule(not an entire block) that is written in the second file will be the definitive one in the website.
the same rule apllies within files, for example:
.ClassOne {
color: red;
}
... othes styling ...
.classOne {
color: Black;
}
In this case the color in the browser will be Black because it was the last one and it overwrites the first one.
There is another rule that can affect styling - The more specific rule will be the definitive one, example:
.one .two .three {
color: red;
}
.two .three {
color: blue;
}
.one .three {
color: green;
}
<div class="one">
<div class="two">
<div class="three">
some text
</div>
</div>
</div>
Question: In which color will the text show?
Answer: red.
Why? because in the case above, we call the .three element in a more specific way when we declared the red color.
check it here:
https://jsfiddle.net/wxaw3205/
The same example with more elements:
https://jsfiddle.net/wxaw3205/1/
The last way is using the !important declaration, it provides a way for You to give a CSS value more weight than it naturally has.
For the last example, lets assume that we have the same html markup of the example above, which will be the color now?
.one .two .three {
color: red;
}
.two .three {
color: blue;
}
.one .three {
color: green !important;
}
Answer: green.
Link to live example: https://jsfiddle.net/wxaw3205/2/
And just a little tip: never style the element using the style="" attribute, unless you have too! and either the !important.
Most of the time when you have to use them its because you'r stylesheet needs to be reordered.
That's all, I hope it helped you understand.

Apply <style> rules to another element instead

I have a <style> element that applies some global styles, like A { color: red } as opposed to my stylesheet that styles A { color: green } (purely as an example).
How can I modify all of the styling in my <style> element so that are "contained" and only apply the styling to children of a parent element I specify.
A { color: red } becomes #myelem A { color: red }
.myclass { display: none; } becomes #myelem .myclass { display: none }
Would I have to find the <style> element, parse the contents, replace each selector then update the element contents with it fixed?
Is there an alternative to modifying the contents of my <style> element?
Why am I doing this? I have HTML that is stored in a database that I want to edit (this is a CMS). The HTML can contain <style> elements, and I cannot trust who writes the CSS to write it in scope. I could prevent users from using the <style> element, but I'd rather not. I have no control over the original CSS. Only what I get back in my server/clientside code.
If all else fails, I might have to load it into an iFrame... :(
Ooooooo Firefox supportes <style scoped> which only applies to the parent where the <style> element is located in the DOM. Too bad it's not supported in any other browser. :(
As you mentioned, you can use:
<style scoped>
...
</style>
Although it is only supported natively in Firefox, you can use this jQuery polyfill to get it to work in other browsers.
Use the child selector:
#yourElement > a { color: green; }
JQuery:
$( "parent_type > children_type" ).css("param","value");
example
$( "#myid > div" ).css("display","none");
here's a link
JSFiddle

How to change one element while hovering over another

I have looked at several other questions but I can't seem to figure any of them out, so here is my problem: I would like to have a div or a span, when you hover over it an area would appear and would be like a drop down.
Such as I have an div, and I want to hover over it and have it show some info about the item I hovered over
<html>
<head>
<title>Question1</title>
<styles type="css/text">
#cheetah {
background-color: red;
color: yellow;
text-align: center;
}
a {
color: blue;
}
#hidden {
background-color: black;
}
a:hover > #hidden {
background-color: orange;
color: orange;
}
</styles>
</head>
<body>
<div id="cheetah">
<p>Cheetah</p>
</div>
<div id="hidden">
<p>A cheetah is a land mammal that can run up 2 60mph!!!</p>
</div>
</body>
</html>
But this ^ doesn't seem to work, I don't know why... and if there is a way to do that in CSS, I would like to know, but I want any and all suggestions.
You can achieve this in CSS only if the hidden div is a child of the element you use for hovering:
http://jsfiddle.net/LgKkU/
You cannot affect a non-child element using :hover from within CSS2, which is supported by all common browsers.
You can affect a sibling element using CSS2.1 selectors, like so:
a:hover + .sibling { ... }
However, this only works for direct siblings. This means you could have HTML like this:
<p>Cheetah <span class="sibling">Blah Blah Blah</span></p>
Notice that the a and the span are direct siblings.
Here's a fiddle showing the siblings working: http://jsfiddle.net/vUUxp/
However, not all browsers support the CSS2.1 sibling selectors, so you need to decide based on your target audience if you can use this or not.
Edit: Corrected my mistake on the CSS version for the + selector: it's 2.1 that defines it, not CSS3. I also added a link showing browser support. Otherwise, the answer is the same.
Or, if you're open to it, use jQuery.
Something like this would work:
$("#element") // select your element (supports CSS selectors)
.hover(function(){ // trigger the mouseover event
$("#otherElement") // select the element to show (can be anywhere)
.show(); // show the element
}, function(){ // trigger the mouseout event
$("#otherElement") // select the same element
.hide(); // hide it
});
And remember to wrap this in a DOM ready function ($(function(){...}); or $(document).ready(function(){...});).
You can absolutely do this in CSS3 now using the ~ adjacent sibling selector.
triggerSelector:hover ~ targetSelector {
display: block;
}
For example, if you want a tooltip to appear when hovering over an adjacent button:
.button:hover ~ .tooltip {
display: block;
}