-
Notifications
You must be signed in to change notification settings - Fork 693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[selectors] Postcede selector #1705
Comments
FWIW, some similar discussion appeared on www-style several days ago: https://lists.w3.org/Archives/Public/www-style/2017Jul/0025.html |
Selectors Level 4 has the theoretical possibility to do this as |
This feels like a feature that falls outside of the limitations of CSS so I'm not optimistic that a 'previous element selector' will ever happen. However, it is something that is easily attainable with JS via Almost half of the styling plugins I've built include some kind of previous selector functionality (7/18 plugins at the time of posting this) including a simple JS mixin explaining my take on it: a selector that grabs the immediately preceding element sibling of any element(s) matching a given selector. Here are some demos:
After implementing this functionality a few different times in a few different ways I still haven't found too many compelling use cases for its inclusion. Most of the time I hear people wishing for a previous element selector is when styling forms, where there's a desire to style different elements based on the state of an element that appears after another one in HTML. In these cases the solution often requires using JavaScript to babysit the elements in the form and apply a class to a parent or the previous element at the Right Time™. It's definitely a feature that would be 'nice to have' for prototyping, but from what I can see having this in CSS would only abstract away a few lines of JS in a layout and would be needed pretty infrequently. Also, the difference between 'immediately preceding sibling' and 'matching older sibling(s)' is kind of like the difference between 'parent' and 'matching ancestor(s)', and the latter would perform even worse. Can anybody else think of any compelling use-cases for a previous element selector in CSS? I've got plugins ready to go we can use to test out the ideas and see if they're worthwhile, what can we test? Here's the example you gave of selecting all <div id=eqcss>
<label>label</label>
<input>
</div>
<style>
@element #eqcss input {
$prev {
color: lime;
}
}
</style>
<script src=http://elementqueries.com/EQCSS.js></script> <div id=selectory>
<label>label</label>
<input>
</div>
<style>
#selectory label[test="this.nextElementSibling.tagName == 'INPUT'"] {
color: blue;
}
</style>
<script src=http://tomhodgins.github.io/cssplus/selectory.js></script> <div id=reprocss>
<label>label</label>
<input>
</div>
<style process=auto>
${prev('#reprocss input', `
color: orange;
`)}
</style>
<script src=https://rawgit.com/tomhodgins/reprocss/master/mixins/prev-selector.js></script>
<script src=https://rawgit.com/tomhodgins/reprocss/master/reprocss.js></script> |
So you mentioned forms and how JS would have to be used to "babysit" the elements. With the introduction of With all this you don't need JS to have elements next to each other. Also this came from this talk https://www.youtube.com/watch?v=7kVeCqQCxlk. Here the speaker advocates for removing as much as possible of what he describes as layout tags. He says that it is desirable for the HTML to be as much as possible content orientated. Lastly, not using JS also allows to have separation between View design and controller which seems to be good design and how the web is set up. |
Hmm, I'm not quite sure what you're meaning here about CSS grid - selecting a previous element is something that could be done regardless of the layout you're using. One way I do witness people working around the lack of previous element selector is by using (abusing?) the flexbox Here's how people use/abuse flexbox order to fake a previous selector: <div id=flex>
<input type=checkbox>
<label>label</label>
</div>
<style>
#flex {
display: flex;
}
label {
order: 1;
}
input {
order: 2;
}
input:checked + label {
color: red;
}
</style> This way the <section id=prev>
<label>Label 1</label>
<input>
<label>Label 2</label>
<input>
<label>Label 3</label>
<input>
</section>
<style>
.example { color: red }
</style>
<script>
function prevver() {
var tag = document.querySelectorAll('#prev input')
for (var i=0; i<tag.length; i++) {
var prev = tag[i].previousElementSibling
if (tag[i].value == '') {
prev.classList.add('example')
} else {
prev.classList.remove('example')
}
}
}
var tag = document.querySelectorAll('#prev input')
for (var i=0; i<tag.length; i++) {
tag[i].addEventListener('input', prevver)
tag[i].addEventListener('blur', prevver)
}
window.addEventListener('load', prevver)
</script> |
A problem with using the ordering property is that is breaks the other selectors since you cannot correctly select the button after a label in the above case. When I have seen people wanting to select predecessor they also want to select successor as well |
I also believe that this won't break the single pass objective since it does not allow for arbitrary depth searching, just at the same level, not even a parent selector. |
I'd like to +1 this feature request. On more than one occasion, I'm left to deal with poor HTML coding by someone else's hand and re-coding it is either not an option or too much of a pain. I recently was met with an obstacle where an input was put inside of a label and the text for the label wasn't wrapped in anything, it was part of the label itself. In other words, the input was completely cut off from any CSS styling because someone wasn't thinking... In this use case I was trying to style :checked vs :not(:checked) but found it was impossible because the checkbox input was the last sibling in the chain. Styling a previous selector is obviously not ideal and the HTML should be coded properly to account for these types of situations, however many of us are left to the coding of other people who either don't know any better or weren't paying attention. "I need a fix now, not 6 months from now when xyz maintainer feels like getting around to fixing his code". Since I don't code by nature, coming up with javascript workarounds or re-theming workarounds to someone else's code isn't possible. Being able to style a previous selector based on a sibling condition, would be fantastic. On a side note, do a google search for "CSS Previous sibling" and you'll find a lot of other folks who want to use it for their own various reason, but are left with answers of "You can't". If the people using CSS want it, why can't we have it? Am I wrong in saying the DOM can handle it? https://www.w3schools.com/jsref/prop_node_previoussibling.asp Code Example:
|
Sure. Say I'm writing a basic webpage (just HTML and CSS). It has a number of sections, either nav,
section {
height: 100vh; /* Fills the screen */
overflow: hidden;
} For clarity, I want to stick an arrow at the bottom of these sections so that readers know that they can keep scrolling. This arrow isn't really a part of the document's contents (and shouldn't be rendered in alternate environments like Reader View), so it makes sense to add using CSS: nav::after,
section::after {
display: block;
position: absolute;
bottom: 0;
margin: auto;
width: 1em;
content: "↓";
} Naturally I don't want an arrow pointing towards nothing, so I can hide it on the last child. nav:last-child::after,
section:last-child::after { content: none } However, my document might have a page footer (a
nav:immediately-precedes(footer),
section:immediately-precedes(footer) { content: none } I kept the above example as simple as possible but things get even more complicated if we consider a grid layout; suppose I want to display a page footer at the right-hand side of the grid rather than at the bottom. This could potentially affect the positioning of all preceding elements. (It could happen! In such cases, one might even want both TL;DR: forms and web apps are definitely not the place where this selector seems most useful; vanilla text-based webpages with innovative typographic layouts are. Not having this feature leads to inaccessible webpages, by encouraging people to code documents whose tree doesn't reflect what is rendered on the page. This breaks important features like Reader View. (As a sidenote, since |
My syntax suggestion would be Sebastian |
Similar to the
element1~element2
andelement1+element2
selectors. However, this will select in the other direction.Suggestion:
element1:precedes(element2)
Example:
label:precedes(input)
will select all labels that immediately precede any input tags.I was also thinking about suggestion the opposite to the
~
selector but that seems like it would have much more speed difficulties compared to just this and to me at least it seems like it would be less used.The text was updated successfully, but these errors were encountered: