I know I can use [dir='ltr'] or [dir='rtl'] to select elements that have a dir attribute with a specific value.
so I can define for example
[dir='ltr'] .float-end {float:right}
[dir='rtl'] .float-end {float:left}
to get a .float-end class that floats right or left when inside an element with ltr or rtl respectively.
The problem starts when I have an ltr sub part of a document that is rtl.
<div dir="rtl">
<div dir="ltr">
<div class="float-end"></div>
</div>
</div>
What happens is that both rules match... and I only want to match the 'ltr' case in this scenario.
The problem gets worse if I want to create classes such as start-20px and end-20px to provide left:20px and right:20px and vice versa depending on context.
Would result in both left:20px and right:20px being applied....
I am looking for suggestions on how to overcome this.
Is there a way to depend on the nearest value of an attribute of any given type of element?
This is all done within the context of LESS mixins if it helps some how...
Thanks
The problem lies in the fact that the attribute selectors currently available in CSS have no document semantics. For example, you can't use attribute selectors to express some attribute value that is inherited from some other element. This is because as far as an attribute selector is concerned, if an element's attribute doesn't have a certain value specified on the element itself in the document tree, then it will not match the selector, even if the value is derived from elsewhere.
As mentioned, you could limit selection to the closest ancestor using the > combinator, but this requires the immediate ancestor to have the specified attribute, which of course you won't be able to guarantee is the case unless you make sure of it yourself. But if you are able to modify your markup, then that really is the best way to do this, even if it means a little bit of redundancy in your markup. I don't think even LESS by itself would be able to help you, as it still depends on the structure of your markup, which it cannot anticipate.
For what it's worth, Selectors 4 introduces a :dir() pseudo-class which carries semantics of element directionality based on the rules of the document language, something that attribute selectors alone cannot accomplish. For example, both the div and the p in the following example would match :dir(ltr), but only the div is [dir='ltr'] because the p has no dir attribute specified:
<div dir="ltr">
<p>Left-to-right text</p>
</div>
In your case, you would be able to just use .float-end:dir(ltr) and .float-end:dir(rtl) respectively; you wouldn't even need to have the pseudo-class on an ancestor.
The :dir() pseudo-class compared with the [dir=] attribute selector is similar to :lang() and [lang|=], which I explain here.
Of course, being a new proposal, :dir() isn't implemented anywhere (with the curious exception of Firefox — I'm guessing Mozilla thought of the idea, implemented it, then proposed for it to be standardized). In the meantime, you'll have to work around it by going the route I des
There is now a proposed solution for this in the CSS spec: Logical Properties. Basically instead of applying different property values based on some other element's dir attribute, browsers are going to start having property values that are directionally aware.
So in a perfect world, once these have full support you could write:
.float-end {
float: inline-end;
}
These new values will exist for lots of properties, not just float. Support as of July 2019 is pretty much everybody but Microsoft (IE/Edge), go figure.
Well, I can not give a solution to your first question (about floats), but I can give you one about the second (left / right properties).
As stated by the w3c
If neither 'left' nor 'right' is 'auto', the position is
over-constrained, and one of them has to be ignored. If the
'direction' property of the containing block is 'ltr', the value of
'left' wins and 'right' becomes -'left'. If 'direction' of the
containing block is 'rtl', 'right' wins and 'left' is ignored.
O.k.
So having learned that what I expected just does not work (at least not as of now [June 2014]),
I ended up with the following LESS based solution:
// provide a mixin to use two different rule sets depending on the current direction.
.ltr(#ltrRules) {
body[dir="ltr"] & , body[dir="rtl"] [dir="ltr"] &, body[dir="rtl"] [dir="ltr"]& { #ltrRules(); }
}
.rtl (#rtlRules) {
body[dir="rtl"] & , body[dir="ltr"] [dir="rtl"] &, body[dir="ltr"] [dir="rtl"]& { #rtlRules(); }
}
.bidi(#ltrRules,#rtlRules) {
.ltr(#ltrRules);
.rtl(#rtlRules);
}
// padding
// ------------------------------------------
.padding-start(#p) {
.bidi(
{ padding-left: #p } ,
{ padding-right: #p }
)
}
so using .padding-start(10;) on some SELECTOR
.my .selector {
.padding-start(10px);
}
will eventually generate the following CSS:
body[dir="ltr"] .my .selector,
body[dir="rtl"] [dir="ltr"] .my .selector,
body[dir="rtl"] [dir="ltr"].my .selector {
padding-left: 10px;
}
body[dir="rtl"] .my .selector,
body[dir="ltr"] [dir="trl"] .my .selector,
body[dir="ltr"] [dir="trl"].my .selector {
padding-right: 10px;
}
The compromise is that I can not change the direction multiple times going into the depth of the document and that the initial seeing of the direction must be on the body tag.
That siad, if for some absurd reason I WILL get to some point in the future when I will have to change the dir more then twice I can just use the same method and add handling for body[dir="ltr"] [dir="rtl"] [dir="ltr"] & and so on...
With some luck in a few years someone will understand that it is important to add the semantics of start and end that get interpreted as left and right respectively in LTR contexts and vice versa in TRL contexts making all my macros redundant... [as has already been done in text-align for example].
I know this is a very late reply but it could help someone if I got the question right.
Does this make sense?
[dir="ltr"] *:not([dir="rtl"]) .float-end,
[dir="ltr"] > .float-end{
float: right;
}
[dir="rtl"] *:not([dir="ltr"]) .float-end,
[dir="rtl"] > .float-end{
float: left;
}
JSFiddle here
Related
So, I'm not sure what I've stumbled upon here. I'm working with some CSS and I know it is common place to do something like this:
#content{
/* Style the content div. */
}
#content p{
/* Style all p elements in the content div. */
}
I'd like to give one specific p element a float:right style. Only one such p element will occur in the content element. Naturally, I'd just give this element an id, but then I had the idea to do it this way:
#content #right_floating_p{
float:right;
}
This works when I run the code, but I was wondering about best practice and whether or not this actually does anything scope wise. I could just as easily define a separate id for right_floating_p, but to me it feels natural that it should be defined with the content id because it will be used only on one p element inside the content element.
If anyone has any information about this syntax, please let me know. Thanks!
My recommendation is to only include the last ID. This is fairly standard separation of concerns. What if you want to change the first ID #content, but the last one #right_floating_p still makes sense and shouldn't change? There is more room for error if you specify something unnecessarily.
Other reasons this is good:
Smaller, faster (but barely) download size for your users.
More readable, in my opinion.
Faster (but barely) performance.
Over-qualifying tags is bad practice in general, as far as performance goes. Browsers read your selectors from right-to-left, by the time it interprets your #content selector, that information is pointless. My advice is to not trust that the browser will optimize for this.
Alvaro nailed it in his comment above.
The id must be unique on the page, but not necessarily across the whole site. So, for instance, if you had the #right_floating_p element on every page, but it had a #content element as an ancestor only on a certain page where you wanted it styled differently, then you'd want to use the #content #right_floating_p selector to apply the context-specific style.
I would suggest only using the most precise selector as you can, not only for readability and file size, but also for specificity.
CSS selectors have a specificity to them, so if you were to override it later (such as with a media query), the more specific selector will override the less specific one.
#content #right_floating_p {
color: red;
}
div #right_floating_p {
color: green; /* Will not apply, as it's less specific */
}
p {
color: black; /* Even less specific */
}
It will work having the first selector, but it's not necessary.
What does the CSS standard say about unsupported expressions? How should a browser deal with them? How do actual browser implementations deal with them?
I'm implementing a CSS property optimizer (for a minifier project), and we want to leave CSS fallbacks intact. Our goal is to optimize the CSS as much as possible but in such a way that it should render exactly the same as the original.
This is why it's essential for me to understand how these things work.
Simple properties
For simple properties, it's really easy.
Let's say we have this:
div {
color: #f00;
color: rgba(1,2,3,.4);
}
In this case, if the browser doesn't support rgba then the first declaration #f00 wins. There is no question here.
Shorthands
However, how does it work with shorthand properties?
Here's some code:
div {
background: #f00;
background: rgba(1,2,3,.4);
}
How does the browser render this if it doesn't understand rgba? As you know, the syntax of background is: background: <color> <image> <repeat> <attachment> <position>; and such a shorthand declaration overrides any of the 5 fine-grained declarations that came before it; so the difficulty lies in which one of the 5 fine-grained properties the browser tries to assign the unknown token to. I have several possibilities in mind:
the browser decides it doesn't understand the latter declaration at all and drops it entirely
the browser thinks that rgba(...) represents a background-image and even though it doesn't know what to do with it, clears out the previous background-color as well
the browser thinks that rgba(...) represents a background-color and since it doesn't understand it, falls back to using #f00 instead
Let's make it even more interesting, say we have this:
div {
background: #fff url(...) no-repeat;
background: rgba(1,2,3,.4) linear-gradient(...) repeat-y;
}
How does a browser interpret this CSS snippet, ...
if the browser doesn't understand rgba?
if the browser doesn't understand linear-gradient?
if the browser doesn't understand repeat-y?
if the browser doesn't understand any two of the three?
if the browser doesn't understand any of the three?
The parsing rules in section 4.2 of the CSS2.1 spec speaks in terms of declarations, which refer to entire property-value pairs, regardless of whether the properties are shorthand or not:
Illegal values. User agents must ignore a declaration with an illegal value. For example:
img { float: left } /* correct CSS 2.1 */
img { float: left here } /* "here" is not a value of 'float' */
img { background: "red" } /* keywords cannot be quoted */
img { border-width: 3 } /* a unit must be specified for length values */
A CSS 2.1 parser would honor the first rule and ignore the rest, as if the style sheet had been:
img { float: left }
img { }
img { }
img { }
A user agent conforming to a future CSS specification may accept one or more of the other rules as well.
Notice that the third example shows the use of an illegal value for the background shorthand property resulting in the entire declaration being ignored.
Although the spec speaks of illegal values, as far as an implementation is concerned an unrecognized value and an illegal value are the same thing, since either way the implementation doesn't know what to do with such a value.
So the answer to the first part of your question is
the browser decides it doesn't understand the latter declaration at all and drops it entirely
And the answers to the second part are all the same: the latter declaration is ignored entirely.
As far as I know, if a browser cannot understand even a part of an expression, then it handles the property as syntactically wrong, and ignores the whole line.
I've been reading up on specificity and, quite frankly, I'm surprised that I didn't know about this properly before, since I've witnessed the very issues that specificity can give if CSS is declared in the wrong manner.
So, I've been doing a little research on the subject, and I now understand the rule for calculating specificity. However, during my findings, I've been left with three questions which I was hoping you guys could help me out with.
Firstly, when relating to CSS specificity, I've noticed that one source includes pseudo elements in the calculation, while another tells you to leave them out of the calculation. Is this purely an optional thing, or should I include them?
Secondly, is there any specific reason why I should declare classes above identifiers? For instance, I've already sectioned my development CSS file, and in the 'footer' section, I have #footer, #footer-container, .grid and .one-third, declared in this order. Is this perfectly fine, or should I switch them around? The defined rules are below, to show that both classes don't contain any conflicting properties:
#footer {
background: #e4e4e4;
border-top: 1px solid #eeeeee;
border-bottom: 1px solid #666666;
overflow: hidden;
padding-bottom: 1em;
width: 100%;
}
#footer-container {
margin: 0 auto;
width: 100%;
min-width: 1000px;
}
.grid {
margin-right: 2.1%;
float: left;
display: inline;
position: relative;
}
.one-third {
width: 31.9%;
}
Lastly, just a quick question about listing CSS properties in alphabetical order. I fully understand that this is optional, but using my declaration for #footer above as an example, is there any preference for border, margin or padding, as in alphabetical (bottom; left; right; top), or declared as written in shorthand (top; right; bottom; left)?
Thank you very much!
Firstly, when relating to CSS specificity, I've noticed that one source includes pseudo elements in the calculation, while another tells you to leave them out of the calculation. Is this purely an optional thing, or should I include them?
This is news to me; it looks like pre-CSS2.1 pseudo-elements were originally supposed to be ignored when calculating selector specificity. The article that says to leave them out of the calculation was published almost a decade ago, right in the middle of CSS level 2's refactoring. Here's what the 1998 CSS2 recommendation says (which, for reference, is also quoted in that article, but the URL that it links to redirects to the latest revision of the spec where it's changed):
A selector's specificity is calculated as follows:
count the number of ID attributes in the selector (= a)
count the number of other attributes and pseudo-classes in the selector (= b)
count the number of element names in the selector (= c)
ignore pseudo-elements.
In CSS2.1, as well as the latest Selectors standard, pseudo-elements must be counted like normal type selectors when calculating specificity.
Perhaps what's even more curious is that CSS1 had the same rule for pseudo-elements in terms of specificity as the current standard:
Pseudo-elements and pseudo-classes are counted as normal elements and classes, respectively.
This leads me to believe that the change in CSS2.0 was ultimately reversed in CSS2.1 so it wouldn't break existing (legacy) stylesheets that happened to rely on the behavior, and/or because it simply didn't make sense not to include pseudo-elements since you apply styles to them like you do with actual elements.
Secondly, is there any specific reason why I should declare classes above identifiers? For instance, I've already sectioned my development CSS file, and in the 'footer' section, I have #footer, #footer-container, .grid and .one-third, declared in this order. Is this perfectly fine, or should I switch them around?
There should be no difference whether you place your classes before your IDs, as long as your two classes follow the order they are in and your two IDs, likewise. Even assuming that all of these rules happen to match the same element, the IDs should take precedence over the classes for any properties that need to be overridden.
Lastly, just a quick question about listing CSS properties in alphabetical order. I fully understand that this is optional, but using my declaration for #footer above as an example, is there any preference for border, margin or padding, as in alphabetical (bottom; left; right; top), or declared as written in shorthand (top; right; bottom; left)?
If you are declaring the longhand properties separately, then it's entirely up to you how you want to order them. I would certainly follow the order already laid out by the shorthands for the sake of simplicity.
FYI, the order in the shorthands is laid out the way it is because if you literally connect the dots, the order is actually clockwise starting from the top.
Many would argue not to use IDs at all for styling to avoid issues with specificity. You CAN use classes over and over or you can just use them for one element like an ID. I agree that it is an unnecessary issue to battle with when its just as easy to use a class. And before you say "but sometimes I cant change the markup." let me just say attribute selector. These may be a little more to type but to avoid problems with specificity I think its worth it. So
div[id='yourID'] {
}
and you dont have to worry about not being able to overwrite this later. This is especially helpful when you work on a team.
I'm reading the book: CSS Mastery: Advanced Web Standards Solutions, and finding the css code inside is almost writed in this format:
elementName#idName
elementName.className
but, I'm used to write code ignoring element name with this format:
#idName
.className
so, I want to figure out what difference is between the two format.
Actually, I understand when should use type.class. And, I just want to find out the impact when I use type.class insead of only using .class when there is only one kind of tag here.
There must be some impact on performance.
Here's a real life scenario as when to use elementName and when to just use class or id name:
HTML:
<a class="blue">I'm blue and underline</a>
<span class"blue">I'm blue and bold</a>
CSS:
.blue {
color:blue //will make both <a> and <span> blue
}
a.blue {
text-decoration:underline // will make only the <a> tags underline
}
span.blue {
font-weight:bold //will make only the <span> tags bold
}
but remember when it comes to IDs you should not have duplicate IDs on your page anyway, this is more practical for classes
The difference between the two is that the first:
element.class
Is calling the element with that specific class.
And the second:
.class
Is calling all elements that contain this class
I think that the element inclusion in the selector is a holdover from days where some browsers required it (I think IE5 does, but I could be wrong). This is no longer necessary, and it does not make sense to include element selector for at least three reasons:
It slows the selector down since the element selector is slower than the other two -- especially id. Assuming selection is optimized so that fast selection is done first (e.g. the element with the matching id is found before the element selector is checked), there is still the additional step of checking the element selector.
It's not as extensible since you can't change the element without also having to change the selector. The implication is also that div.class would function differently than label.class, but I think that the class should be descriptive enough.
It changes the specificity of the selector. This could be very frustrating for some developers who may want to change <div class="foo"> from green to red:
div.foo { color: green; }
/* below is not applied since the above has higher specificity */
.foo { color: red; }
I've never heard an argument that supports type.class unless old browsers need to be supported.
I was looking at a css file today and found the following rule set:
div.with-some-class {
display:block;
margin:0;
padding:2px 0 0 0;
*padding:1px 0 0 0;
font-size:11px;
font-weight:normal;
*line-height:13px;
color:#3D9AD0;
}
What does the star mean in *padding and *line-height?
Thanks.
This is the "star property hack" along the same lines as the "underscore hack." It includes junk before the property that IE ignores (the * works up to IE 7, the _ up to IE 6).
In CSS? Nothing; it is an error.
Due to bugs in some versions of Internet Explorer, they won't correctly ignore the invalid property name, so this is one way of providing CSS that is specific to those browsers.
Using conditional comments is clearer and safer though.
The asteriks character is a valid wildcard in CSS. Use of it alone means the following CSS properties will be used against all element nodes in the DOM. Example:
*{color:#000;}
The above property will be applied to all DOM elements, thereby defeating the natural cascading in CSS. It can only be overridden by specifically tageting DOM elements where that targeting begins a unique identifier reference. Example:
#uniqueValue div strong{color:#f00;}
The above property will override the wildcard and make the text of all strong elements that occur in a div inside an element with an id attribute value of "uniqueValue".
Using a universally applied wildcard, such as the first example, can be a quick and dirty method for writing a reset stylesheet. It is quick and dirty because granular definition of presentation after the wildcard will likely create an extremely bloated stylesheet. If you are going to use the wildcard I would suggest using it more specifically, such as:
* strong{color:#f00;}
The above example will make the text of all strong elements color red regardless of other CSS properties not specified with a unique identifier. This is considered much safer than using the "!important" declaration as that declaration is known to cause interference with natural functionality of the intended behaviors and is a maintanence nightmare.
The asteriks in your example are in the wrong place as they seem to occur inside the property declarations, the code that goes inside curly braces, and that will likely cause an error.
This is a hack for IE7.
If you write this:
.test {
z-index: 1;
*z-index: 2;
}
on all navigator which respect the W3C Standard <div class="test"></div> HTMLElement have a z-index: 1 but for IE7, this element have a z-index: 2.
This is not standard.
To achieve same thing with W3C Standard, follow this steps:
Add some Internet Explorer Conditional Comment (this is a simple HTML Comment for all other navigateur so, it's a standard way).
<!--[if IE 7]><html lang="fr" class="ie7"><![endif]-->
<!--[if gt IE 7]><!--><html lang="fr"><!--<![endif]-->
And use the previous rules like this:
.test {
z-index: 1;
}
.ie7 .test {
z-index: 2;
}