How would one use data-* attributes to replace id in practice? - html

I know, thanks to a previous question, that this is not a good idea but is, apparently, possible. But I'm in a situation where the CMS automatically strips any id=selectors, and I'm trying to find a workaround. (Unfortunately, no JS; any solutions need to be strictly CSS and HTML.)
But, I'm completely new to the idea of data-* attributes, and I'm uncomfortable trying to figure this out on my own, since my own unfamiliarity with how they work isn't conducive to doing it right.
So, here's the question. Say I wanted to recreate something like the CSS :target tabs in this CodePen: https://codepen.io/MarekZeman91/pen/wBwbrp.
Is it possible to replace the id selectors with data-* attributes? And if so, how would I go about doing it? Not just for the example, but in general.

Say you want to replace all elements with an id of X with an attribute of data-X, eg
<div id="tabs">
will turn into
<div data-tabs>
Once you've changed the HTML, you then need to:
(1) Change the CSS. The selector string for an ID is #id; the selector string for an element with a particular attribute is [attributeName]. So #tabs will turn into [data-tabs]. Replace all instances of #tabs with [data-tabs].
Keep in mind that ID selectors have a very high specificity compared to attribute selectors. If the elements you're targeting are matched by multiple clashing CSS rules, changing the ID to an attribute may result in the wrong rule winning, so you might have to change things a bit more until all the rules get applied as expected.
(2) Change the Javascript. Just like above, use the selector string [data-tabs] wherever you used to have #tabs, eg:
var link = document.querySelector('#tabs > .tab-link');
turns into
var link = document.querySelector('[data-tabs] > .tab-link');
You can repeat the above pattern for all IDs present, until none are left.
You can also consider using classes instead, they work just as well, eg change
<div id="tabs">
to
<div class="tabs">
and then use the selector string .tabs everywhere instead of #tabs.

Related

How to block this element with an adblocker

On this twitch site there is an annoying element that I want to remove permanently. On the inspector the element is this:
<div class="menu-button hover-background-primary">
But try as I might, I can't figure out how to write a filter to remove that element with Ublock.
I read that Ublock and ABP use the same syntax. According to this,
##.menu-button hover-background-primary
should do want I want. But I can't block anything with this pattern, I tried it putting the names of other classes there and it never does anything. How does this work?
The two classes are separated only in the html - you need to join them together in the rule declaration. And in the html the "." is never shown but when you target classes in either CSS or javascript - each class needs to be prefixed with a "." otherwise the browser will interpret that you are trying to target a html element with that name - irrespective of whether it is correct or even present.
##.menu-button.hover-background-primary
What this targets is the items that has both the "menu-button class" AND the "hover-background-primary" class
you could even just target the more specific class-
##.hover-background-primary
Those are multiple classnames.
You need the selector .first-class-name.second-class-name, which you can put in filter syntax as desired.

Is it possible to select an element's attribute with a CSS selector?

I'm looking for a way to use a pure CSS selector (not script) to select an element's attribute, not the element itself. I know XPath can do it but can a CSS selector?
Example, given:
<img alt="image" src="photo.jpg">
Can I get to the src attribute with a CSS selector?
Update:
I don't want to set any element's values, I just want to select the text "photo.jpg".
Because CSS selectors originated as a fundamental part of CSS, and CSS can only apply styles to elements (since attributes are just element metadata, not standalone objects), CSS selectors cannot match attributes alone within CSS.
But I suspect you're not actually asking about CSS here. You're asking about selectors alone. You're probably using a web automation tool such as Selenium or one of the numerous HTML parsing libraries out there that support either CSS selectors or XPath. Some of these libraries support non-element selectors in the form of pseudo-elements such as ::attr() (I don't remember which ones), you haven't mentioned which tool you're using so I can't tell you for sure if you could use it. Note that this is not the same thing as the CSS attr() function mentioned in the comments — that is a CSS function, which is a value, not a selector, and therefore it cannot be used in a selector.
But if your library doesn't have such a feature then you'll need to either select the img element directly and query its src attribute separately (again, how you do this depends entirely on what you're using, which is why it helps to be specific about this sort of thing), or use XPath if possible.
CSS Tricks has an article that I believe answers your question:
https://css-tricks.com/almanac/selectors/a/attribute/
If you are trying to set the value of a certain element attribute using css, I'm pretty certain that is impossible for anything other than the content property.
CSS is not a programming language and can't process data.
Its sole purpose it to tell the browser how a certain element should look like, like in coloring a text red.
To process data in a web page you use javascript, which can make use of CSS rules though, to grab a certain type of elements in a web page, for example this, which will return a list of all elements of type img
var imglist = document.querySelectorAll('img');
Now, having a list you can loop through it and get each src like this
Array.prototype.slice.call(document.querySelectorAll("img")).forEach(function(img) {
var imgsrc = img.src;
// imgsrc now holds the image url, in your case "photo.jpg"
});

CSS selector select by div class attributes

<div class="thumbnail-popular" style="background: url('http://images.gogoanime.tv/images/upload/Go!.Princess.Precure.full.1812487.jpg');"></div>
I am trying to get the url component of this div class but I seem to be unable to fetch that specific data in the div class.
I have looked into making use of attributes but my attempts have been unsuccessful so far.
Usage of this CSS selector is through Kimonolabs.
div.thumbnail-popular should get you the element you're looking for — unless there is more than one such element, in which case you will need to narrow down your selector.
For example you will need to find out if this particular element belongs to a specific parent, or is the first, second, ... nth child, or any other information about the surrounding elements in the page that you're working with.
The background URL is in a style attribute on this element, so you will need to extract that attribute as described here. However you will still need to parse the declarations inside the style value in order to get the URL; I am not sure if it is possible to do this through kimono as I am not familiar with it (I'm not sure what its advanced mode really does, and it's difficult to tell from the lone screenshot that is provided in that help article).

Semantic way to select current or active links in navigation menu

Currently the most common way to identify the current link is adding a class to the anchor or its parent:
<li class="active">Home</li>
This technique has a couple of drawbacks:
Adding the class is often delegated to server languages and it means an extra work just for presentation.
Even though there is a convention around the active class name, it's a stupid selector and doesn't seem to be semantically correct.
I tried the following with no success:
I looked for something like the :target pseudo-class, so the selector could be: a:current, unfortunately it doesn't exist yet.
I thought the rel attribute was a good candidate, but I couldn't find any that fit.
Adding and attibute to the nav that sets the current link, but we need to add ids to every link, and CSS will become verbose
<style>
[data-active^="home"] a[id^="home"]{ color:red; }
</style>
<nav data-active="home-link"><ul>
<li><a id="home-link">Home</a>
...
Is there a different way to select current links that is semantically correct?
The purpose of selecting with CSS the current or active link is to give the user a clue about the section or document is currently viewing. As #BoltClock pointed out the active class is semantically meaningless and the question is if there is a semantically meaningful way to select the link that belongs to the section or document the user is visting?
I looked for something like the :target pseudo-class, so the selector could be: a:current, unfortunately it doesn't exist yet.
Indeed, no such selector exists yet, so what you have is already your best bet. The following pseudo-classes sound like they might be what you're looking for, but they mean different things:
:active matches an element that is being designated by the cursor; usually this means an element that is being clicked.
:target matches an element whose ID matches the URL hash fragment, which means it only works for hash fragments and not the URL path itself.
:current appears in Selectors 4, but it means something quite different entirely: it matches the chronologically current element. Since HTML itself doesn't have a concept of a timeline, :current will match nothing (although I can imagine captioning or AT tools making full use of it in an HTML document).
That said, there is in fact a pseudo-class being proposed in Selectors 4 that targets the current document, only it's called :local-link:
a:local-link { color: red; }
Of course, no implementations actually exist yet, so you're stuck with using a class name for the foreseeable future.
As helion3 has pointed out, the reason class names are used is because they're the easiest solution that exists today, and is tried, tested and true tradition dating back decades. Keep in mind that even HTML does not have "current-document" semantics beyond URL fragments, so you're really not going to be able to go any further than a class name or a custom data attribute with a hardcoded value.
I don't disagree with that article you've linked to either, but given there isn't in fact a "semantically correct" approach to this since no pseudo-class exists with the proper semantics, again you're basically stuck with this. If it makes you feel better, note that class names aren't really semantically incorrect in this case, rather they are semantically meaningless, i.e. they have no influence whatsoever on the meaning of the context they are in, or the document as a whole.
current is a concept that CSS doesn't have because CSS isn't involved with route handling. We use the active/current/at class names because it's the easiest way.
Javascript can easily set/remove classes based on routing, as can server-side languages.
Also, navigation structures are different and in your example, it's not the anchor that's active, but the li. That should be left to developers to establish based on the needs of the styles.

Is there any reason for including the tag name with a class or ID selector in CSS?

I'm wondering if there is any difference between div.class and .class as CSS selectors if there is only one tag (the DIV) with that attribute. Same thing for IDs: div#ID and #ID.
Any idea what, if anything, is the difference? For me, I use the class or ID in these situations; but only because it's quicker to type.
They are more specific, so long ones will override the shorter version if they conflict. div.foo will have a specificity of 11 while .foo has a specificity of 10.
Since they are more specific, you know exactly which nodename the class applies to instead of being a universal rule for all node names, this can help if you have a huge application with tons of elements that all have the same class names, it can lessen the time for you to find the element in the source/text editor.
There is only a VERY SLIGHT difference in specificity.
p#id is (0,1,0,1)
and
#id is (0,1,0,0)
in otherwords, the tag itself doesn't hold very much specificity at all compared to an ID, and relying on that kind of tiny specifity to overrule things is almost never needed in my experience.
More importantly, NOT tag-qualifiying selectors is more efficient for the browser to render.
Sticking to just a class or id, as you do, means that your CSS will still apply if the HTML tag is changed to a different tag.
Most of the time, this is probably exactly what you want — classes are there to allow you to add a custom layer of meaning on top of HTML.
In general, your selectors should be the minimum required to express your meaning.
Usually those longer selectors come in handy once the majority of the CSS has already been done. Sometimes you want to tweak a little thing here and there - say - differenciate between p.error and div.error for example. So instead of adding another class - and thus having to touch the HTML - you can simply add an element name to your selector instead, for more fine grained control.
No, there is no difference if you only have DIV tags of the specific class or ID.