This question already has an answer here:
Matching the first/nth element of a certain type in the entire document
(1 answer)
Closed 7 years ago.
I want to match the first H1 element in my whole document. However, right now I'm faced with a problem.
I'm using the following CSS selector:
h1:first-child {
...
}
However, it matches several H1 tags on the page. How can I make it match only the first one?
There is no such selector; all available selectors can only match siblings, not the order of elements of the same name across multiple parents. Your selector would be very brittle anyways.
Instead, simply markup the first h1 with an appropriate class, or match its structure. For example, you might want to match
body>header:first-child>h1
instead.
That is because the selector does now look at the entire document, it looks at the parent. Any time an <h1> is the first child of any element, it will match to that selector. If you only want it to apply to one single <h1> in a document, considering giving it a separate class or ID, or selecting it more specifically based on where you expect it to appear.
For example, on my site I separate each chunk of text into a <div class="box"> which are all present in the <body> of the document. So if I wanted to match only the first <h1> in the document, I could do something like this:
body > .box:first-child > h1:first-of-type { }
This would select the first box only, and then match the first <h1> in that box, simulating the "first <h1> in the document" effect (assuming the first box has an <h1>, which on my website is always true if one exists). I assume you wanted to use the :first-of-type selector here, because the first <h1> in a document doesn't necessarily have to be the first child of a parent.
are you allowed to cheat with jQuery? some times jQuery (javascript) provide(s) elegant alternatives beyond the html and css limitations
$(document).ready(function() {
$('body').find('h1:first').css('color','#0000ff');
}); // ready
That will match every h1 that is the first child of its immediate parent. so if you have like
<div>
<h1></h1>
</div>
<div>
<h1></h1>
</div>
both of those h1 tags are first-children.
Try h1:first
Related
Simplified version: I'm trying to target the second of two spans whenever they are immediately adjacent. From my understanding, a simple span + span should do the job. However, given the following HTML:
<p>
blah
<span>1 blah</span>
<span>2 TARGET ME!!!!</span>
blah
<span>3 SHOULD NOT BE TARGETED (but is)</span>
<span>4 TARGET ME!!!!</span>
blah
<span>5 SHOULD NOT BE TARGETED (but is)</span>
</p>
and this css:
span + span {
background-color:orange;
}
There are 5 spans within that paragraph. 4 spans are rendered with orange backgrounds, but my interpretation of using the "plus" selector tells me that only 2 of those spans should be be orange (spans 2 and 4). What am I missing, or do I need to come up with another approach?
Updated Codepen here
The actual use case is this: a page of user generated content where words can be randomly tagged (a span with a class of "tagged" gets added to each of these tagged words). Each paragraph of content is different. I want to apply a style only when two of these tagged words/spans are right next to each other with no other un-tagged words in-between. This is so I can add more space between two tagged words. However, what's actually happening is that any tagged words beyond the first one in a paragraph get the styles applied, regardless of its proximity to other tags.
Think I may have figured it out, at least for my use case (making sure there’s a space between two tagged words, but no extra spaces added when there’s already a space present before a tagged word.
https://codepen.io/spicedham/pen/XWjNmLL
span::before {
display: inline;
content: " ";
}
It comes down to how browsers handle white spaces. From https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace you learn that “any space immediately following another space (even across two separate inline elements) is ignored.”
Additionally, I was also reminded that any text within the paragraph, but outside of another tag (just plain text) is ignored, so that spans with in a paragaph are considered siblings, even if there is plain text between them.
The element1 + element2 selector is used to select element2 (only the first element) that is directly after element1. That's why your very first <span> never be targeted.
I have two elements, author and citaion of inside a div like follow:
<div>
<h1>author</h1>
<h1>citation</h1>
</div>
If both author and citation exist, I put a comma between author and citation. If only one of them exists or none of them exists, I do not do anything.
Is there a way to do it in CSS or Sass only without JavaScript?
In CSS, you cannot manipulate an earlier sibling by checking the next one. The only way you can check if the second element is there and do something about it is selecting it.
You can solve it using pseudo-element :before. However, it may not be the way you want it because the two elements are on different lines (both <h1>).
So, if you want to make it without JavaScript, I would recommend to consider put both elements in the same line.
h1 span:nth-of-type(2):before {
content: ', ';
}
<h1>
<span>author</span><span>citation</span>
</h1>
I need a pure CSS way to select an element based on part of an HTML attribute value. For example, I want to select this element:
<div data-gt="{'type':'select_me'}"></div>
based on the fact that the element has a data-gt value that contains select. The closest I can get is using [data-gt~=select] as a CSS selector, but that searches for whole words only. So if the word select in the HTML attribute was surrounded by spaces like {'type':' select _me'}, it could find it no problem, but it can't find it because it's preceded by a quote and followed by an underscore.
Note: The example above is a simplified version of what I want to do, so no I can't just change how the HTML attribute is generated and no I can't predict any of the surrounding data in the data-gt attribute.
Just curious if there is a pure CSS way to do this? I know it could be handled with Javascript, but that doesn't work for my purposes.
You can use the * attribute selector:
Represents elements with an attribute name of attr whose value
contains at least one occurrence of value within the string.
[data-gt*="select"] {
color: red;
}
<div data-gt="{'type':'select_me'}">Select Me</div>
<div data-gt="{'type':'please_dont'}">Don't Select Me</div>
If I had a css selector such as #subtab-1, #subtab-2 etc
I could make the wildcard selector as suchdiv[id^='subtab-']
But I cannot figure out how to make a wild card for selectors such as
#subtab-1-sub1
#subtab-1-sub2
#subtab-1-sub2
#subtab-2-sub1
#subtab2-sub2
#subtab2-sub-3
etc...
How can you make something like:
div[id^='subtab-*tab-*'] (*=wildcard)
If I am understanding your question correctly, you are trying to select all elements whose id starts with subtab- followed by a number, followed by -sub followed by another number. It also sounds like you want this selector to not match #subtab-1, only things that have a suffix like #subtab-1-sub1.
This cannot be done with CSS. CSS does not supply a selector that will allow wildcards. You can however hack something together that comes pretty close.
Hacky selector that might work
[id^="subtab-"][id*="-sub"] would match any id that starts with subtab- and also contains -sub somewhere in the id. This will probably work but could cause false positives on things like #subtab-1-subtle or #subtab-something-sub2, #subtab-sub, etc.
Another hacky selector that might work
Making the assumption that #subtab-?-sub? elements are always contained inside of #subtab-? elements and that #subtab-? elements can never contain another #subtab-? element, you could use the child combinator to target them: [id^="subtab-"] > [id^="subtab-"]
Relying on a class instead
A better solution would probably be to give all of the elements you are trying to target a common class, for instance <div class="subtab-sub">, then selecting them all would be as easy as .subtab-sub. Using a class would also yield much faster performance than using attribute selectors.
All the ids start with subtab so use
div[id^='subtab']
I'm not sure you want to use IDs constructed in this fashion as a way to address elements in your HTML. I'd experiment with using classes such as subsubtab, and you could try using the nth-child pseudo-class to individually address subtabs or subsubtabs:
<div class="tabs">
<div class="subtab">
<div class="subsubtab">...</div>
<div class="subsubtab">...</div>
...
</div>
<div class="subtab">
...
</div>
</div>
Then, your CSS would look like
div.subsubtab { color: brown; }
or
div.subtab:nth-child(2) { border: 1px solid red; }
Have a look into this jQuery Selector
I think it can work.
I currently have the following code.
<div id="1">
<div id="2">
<div id="3">
</div>
</div>
</div>
But I cant seem to figure out how I select the div 3 (??).
Any ideas ?
Outside of HTML5 an id beginning with a number is invalid HTML; however with CSS you could, ordinarily, select that div with the following:
As posted by Guffa, the #3 id-based selector in this answer is wrong, the #3 needs to be escaped to #\33 (though I'll explain no further (see his answer!), to avoid shameless plagiarism/repetition)
#3 {
/* CSS */
}
This approach uses an id-based selector (only one element in the document may use a given id, so this is a unique identifier), and is the id-name prefaced with the # sign.
The following, however, is still valid:
div > div > div {
/* CSS */
}
This approach uses the immediate child > combinator, and will select a div that is the direct child of a div (no intervening elements between the two) which is, itself, the immediate child of another div element.
References:
CSS Selectors, Level 1.
CSS Selectors, Level 2.
CSS Selectors, Level 3.
When you have an identifier that starts with a digit, you have to use a character escape to write the CSS rule to match it:
#\33 { ... }
The 33 is the hexadecimal code for the character 3.
If possible, you should avoid having an id that is a number. Using it gets complicated, both from CSS and from Javascript.