Abusing :target to style multiple elements - css

My goals:
Generate a single HTML document with all my output so that it can be copied as a single unit.
Have multiple "pages" within that document that display different parts of the data.
Let the browser's back button do the Right Thing, and support deep-linking.
This is relatively easy to do using the :target pseudo-class to show only the page that I'm looking at (div {display: none} :target {display: block}).
I would like to add two refinements:
A navigation bar that highlights the current page's name.
A main page that appears when there is no fragment identifier (the thing after the #) in the URL.
I have created a solution using empty divs and sibling selectors. The target element (the element whose ID is in the URL fragment identifier) is an empty div, target, and then my CSS says #target1 ~ #page1 { ... } #target1 ~ #link1 { ... }. For a full example see this Fiddle; note that after clicking on the links in the nav bar, the back and forwards browser buttons work as one might reasonably expect (I don't think it's possible to demonstrate deep-linking using jsfiddle).
There are three drawbacks to this solution:
There is a separate selector in my CSS for each page, which can become unwieldy if there are many pages.
The back button works on Chrome and Firefox, but Edge doesn't seem to like this (I haven't tested it anywhere else). My understanding is that the spec is unclear regarding :target and the back button (see also this Webkit bug).
As the question's title says, it feels like I'm abusing... something.
My question is, is there a better way to do what I'm trying to do? I have a slight preference for no JavaScript (mainly because that makes deep-linking more obviously correct).

#Seika85 linked (in a comment) to Navigo, a Javascript router that seems built to do exactly this. I have updated the fiddle to use that instead, which eliminates all the drawbacks I mentioned, at the (minor) expense of having to use (a small bit of) Javascript. Thanks!
new Navigo(null, false)
.on(/target(.)/, function(x) {
$('.active').removeClass('active');
$('#page'+x).addClass('active');
$('#link'+x).addClass('active');
})

Related

Can't edit element on google page, no CSS selector works

I'm trying to make a Google userstyle based on Discord's color scheme. Even though I have no programming experience whatsoever, it has been pretty straightforward (Inspect element > Copy-paste to Stylus) but now there's an element that I can't edit. It's the "next" arrow in the video cards that appear in the results for a search. Here it is: The button on the right.
When inspecting it, the selector just shows up as "element", that didn't work, right-clicking and copying the selector (I'm using FIrefox) also didn't work, and using live CSS editors didn't work either.
I'm guessing it's because they use a fake html element called g-right-button. Just change it to div and you'll be fine.
(You can also just make a g-right-button { .. } selector)
You can also see and change properties from inspector.

CSS selector with parentheses and some sort of index in style inspector

When looking at the elements of a page that I am analyzing using Chrome DevTools, I am seeing the following weird display:
What is that "(1)" in the end? Since the source is user agent stylesheet, I can't drill down any further.
In the Elements panel, I see similar weirdness:
I thought parentheses were not permitted in CSS selector names. What is the "primaryNavId:(primaryLi1)" being used above?
UPDATE:
A more detailed screencap of the "inherited from" line (Styles pane):
When I click on the "inherited from" line, I get the following in the Styles pane:
UPDATE 2 - FIREFOX INSPECT:
Firefox displays the same information in the Elements pane for the item in question, but the Styles panel shows it differently, as follows:
What a mess. Now I understand why you tagged your original question (and this one) css-selectors.
To start, browser developer tools naïvely assume that classes and IDs don't contain any special CSS selector characters and can therefore be represented in CSS selector notation without any escape sequences. So what you get is something that looks like a selector, but on closer inspection is actually malformed. You can see evidence of this in pretty much every browser's developer tools. The breadcrumb navigation, for example, in every one of them will list the li element as li followed by a period (for a class selector) followed by the class name without any escape sequences. Evidently the same appears to hold true for IDs.
It would seem that Google Chrome uses this same notation for "Inherited from" labels. Firefox is smart enough to only list the element's element type (which is far more predictable), i.e. "Inherited from li", and display the actual style rule and the actual selector from the source CSS, but its breadcrumb navigation suffers from the same problem making it kind of moot.
What you're looking at in the element inspector, however, is not a selector. It's an HTML class attribute. The syntactic rules are completely different. And that's why I said that this answer of mine that you previously linked to was completely irrelevant to your original question. But I can see why you're confused, seeing as HTML and CSS are closely related and CSS has dedicated class and ID selectors. (I suspect there wouldn't be any confusion if we were forced to use quoted attribute selectors for all attributes from the beginning — but attribute selectors weren't even around until CSS2.)
As to why the class name that's reflected in the Styles pane is different from the one that's reflected in the element inspector, the reason for that is not clear. Either you're inspecting different elements altogether, or something else is at play (and judging by the cryptic-looking class names, it may well be some funky client-side scripting framework voodoo magic).

How to reset all styles of a div and decedents back to Chrome defaults

I'm not sure this is possible, but id like to set all user styles back to chrome defaults for div and descendants.
I'm building a Chrome plugin that creates a popup on any web page, however due to the fact every page has a plethora of custom styles, trying to track down every inconsistency and overwrite it with my divs (and descendants) custom style, it is becoming a nightmare.
Every time I think I've covered all bases another site implements something else that needs to be overridden.
What would be the easiest approach to standardize my popup in this situation?
One approach I can think of is to (bite the bullet) and get a hold of the the default Chrome CSS styles and implement them into a series of catch all descendant selectors, however surely there is a better way.
If you want to be absolutely sure that the styling of your elements is not affected by the web-page's CSS, there are 2 possible solutions:
Use an iframe to implement your popup. (This solution is "safe" and simple enough, but based on the kind of interaction between the popup and the web-page it might become cumbersome.)
Utilize the Shadow DOM. (This is probably the "proper" solution, but the implementation might be a little more complicated.)
Some resources regarding the 2nd solution:
An introductory tutorial.
An actual example of incorporating the "Shadow DOM" concept into a Chrome extension:
RobW's Display Anchors extension
There is a third option worth discussing and rejecting, which is to reset all the style properties of the div and its descendents to its default value. Pseudo-code:
#my-div, #my-div * {
#for-every-css-property {
%propertyName: initial !important;
}
}
This answer shows an attempt at such a solution. It uses specific values instead of initial which will work in older browsers without the initial keyword, but will not correctly reset elements which have a different default from the base (e.g. user566245 mentions that textarea elements should have a border).
Issues:
Unfortunately initial is not actually the browser's default value.
If we don't use !important above then there is a risk that the page might have provided a rule with a more specific elector which overrides our own. For example if the page specified properties for table > tr > td then this would be applied over our rule because that selector is more specific than #my-div *.
Since we do use !important, any custom styling we want to do after the reset must also use !important on every property.
If the page happens to inject any additional CSS styles after ours that uses !important then these can override our reset.
It is rather inefficient. We are asking the browser to apply a huge bunch of CSS rules to every element under our div.
Vendor-specific properties should also be reset. (E.g. -webkit-animation-name.)
If new CSS properties come into existence in future, you will need to update your list.
Whilst this solution can be applied to current browsers, it is rather horrible, so roll on Shadow DOM! I would recommend the <iframe> solution in the meantime.
I don't know if anyone has tried this, but a more efficient solution might be to use Javascript to detect what site-defined CSS properties could be problematic, and reset only those.

Selecting elements that aren't the :target selector?

I'm attempting to make a simple blog style website using one XML, one XSLT, and one CSS.
For that I'd like to have the option to only view one entry from the xml, and I would like to do it without javascript or php.
I'm trying to do this using the :target selector.
The behaviour I would like to achieve would be;
index.html should show everything
index.html#one should only show the entry with id="one"
index.html#two should only show the entry with id="two"
and so on.
I've found solutions that will display the last sibling, however that doesn't fit. My xslt turns entries into tables, and I can't see how I dynamically could parse the xml to fit that solution.
Is there a way to do this with css, or should I start learning php?
this should be an either/or proposition ... learn PHP. it will benefit you.
but for a CSS-only solution (with a little .htaccess magic) you could do a rewrite of index.html to index.html#all, set your wrapping div to have ID of all (or whatever your wrapper ID is), then set the :target CSS for #all to show everything.
#all .YouWantToHide {
display:none;
}
#all:target .YouWantToHide, #one:target, #two:target {
display:block;
}
This will hide everything by default on the normal page (which will never be visited, it just sets the tone for the specific items to show and other to hide later), show on the #all target (which is now the default page), and the specific items will show as needed while the others will hide.

Removing a word from a <p> only using css

Due to mod rights on a site, I can only add css (no js etc...). When users input text in a comment box, it saves it and then displays it as a <p>. is there any way through css i can search for a specific word in the <p> tag and remove/censor it?
Thanks
There is no practical solution for that ( You may be able to select elements based on the value and hide them in CSS3 but it wouldn't be cross-browser friendly, if at all possible ). I'm afraid you'll have to use JS/server-side for a real solution.
On the hacky side of things and for IE only, you may be able to use an expression and display:none elements which contain certain strings in their nodeValue, it wouldn't work for modern browsers.
If parent element in this case input field has class or id you can hide elements inside like this
textarea#mytextarea p
display:none;
}
Once upon a time, there was a pseudo-class :contains() in the wonderful spec of CSS3 selectors ... but it disappeared early and afaik well before any implementation.
A JS solution has one problem: search bots and any user without JS (or displaying the source code) will see the f***ing original text :)

Resources