Jack1991 Jack1991 - 28 days ago 9
jQuery Question

You can only use an ID once, what exactly does that mean?

I've read that you can only use an ID once in CSS. I've run into something strange that I don't understand and I was wondering if anyone can shed any light on this?

My header contains a basket button with the following markup:

<div id="basket-button-desktop">
<div id="basket-button-inner"></div>
</div>


Then there is a media query that replaces the menu button above with the following version when the window is less than 580px.

<div id="basket-button-mobile">
<div id="basket-button-inner"></div>
</div>


I have a jQuery animation that upon scroll, changes the colour of both the header and `#basket-button-inner The outer divs in the examples above both have separate IDs, whereas the inner divs nested inside have the same ID.

When the screen is wider than 580px, the background colour of
#basket-button-inner
obeys the jQuery and changes from blue to pink as you scroll down the page. When the screen is below 580px wide, it ignores the value set in the jQuery and it stays blue.

Why is this – is it because I've used the same ID twice in my markup?

When I read that you can't use the same ID twice, I assumed it meant that you can't give two different objects the same ID and expect different CSS codes you give them to work. I didn't think it meant you can't put the same object with the same ID in different places throughout a page.

When I change the ID to a class for this div, it works.

I'm not sure what to make of this. Any advice would be greatly appreciated.

I've put two jsFiddles below, the first one is the problem one with IDs, the second is the one with the IDs replaced with classes.

I've included the code from the first fiddle.

https://jsfiddle.net/75dtb1zk/37/

https://jsfiddle.net/75dtb1zk/38/

HTML

<header id="header">
<div id="header-inner">
<ul id="menu">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>

<div id="basket-button-desktop">
<div class="basket-button-inner"></div>
</div>

<div id="basket-button-mobile">
<div class="basket-button-inner"></div>
</div>

</div>
</header>

<div class="content">

</div>


CSS

html {
position: relative;
height: 100%;
background-color: darkorange;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
#header {
position: absolute;
height: 50px;
width: 100%;
background-color: transparent;
border-bottom-color: black;
border-bottom-width: 2px;
border-bottom-style: solid;
transition: all .5s;
}
#header-inner {
height: 50px;
width: 100%;
}
ul#menu {
display: inline-block;
}
ul#menu li {
color: green;
display: inline-block;
margin: 0px 20px;
}
#basket-button-desktop {
display: block;
float: right;
width: 75px;
height: 55px;
cursor: pointer;
}
#basket-button-mobile {
display: none;
}
.basket-button-inner {
width: 20px;
height: 20px;
float: right;
margin: 15px;
background:blue;
}
.content {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
width: 85%;
margin-top: 80px;
margin-left: auto;
margin-right: auto;
padding-top: 20px;
}
@media only screen and (min-width: 0px) and (max-width: 680px) {
#basket-button-desktop {
display: none;
}
#basket-button-mobile {
display: block;
float: right;
width: 75px;
height: 55px;
cursor: pointer;
}
}


jQuery

jQuery(document).ready(function($) {

$(window).scroll(function() {

if ($(this).scrollTop() > 75) {

$("#header-inner").css({
"position": "fixed",
"top": "-55px",
"background-color": "#fff",
"box-shadow": "rgba(0, 0, 0, 0.1) 0px 1px 0px 0px",
"visibility": "hidden"
});

$(".basket-button-inner").css({
"background": "pink"
});

} else {

$("#header-inner, .basket-button-inner").removeAttr("style");
}

if ($(this).scrollTop() > 150) {

$("#header-inner").css({
"transition": "all .5s",
"transform": "translate3d(0px,55px,0px)",
"visibility": "visible",
});

} else {

$('#header-inner').css({
"transform": "translate3d(0px,0px,0px)"
});

}


});

});

ajm ajm
Answer

Ids must be unique within a document (like an entire HTML page). That's the hard and fast rule set forth by the W3C: once you use an ID in one place, you shouldn't use it again somewhere else within that document.

Why? Well, think about what would happen when you try to run something like document.getElementById('basket-button-inner') against your document.

What element would get returned? Here, javascript expects IDs to be unique, but they're not in your case. So, which element would that snippet select?

By violating the rule, you're going to cause strange and wonderful things to happen when you use built-ins and other functions that expect IDs to be unique.

Will your page display if you re-use that ID a bunch of times? Sure. Will elements with that duplicate ID be styled properly? You bet. Will your page break in strange and unusual (and hard-to-debug) ways, especially when you try to select one of those elements with javascript? Yep.

For styles that should be repeated among any number of elements, use classes. This is what they're for, and they can be used as many times on as many different elements as your document requires.

Think of it this way: classes define a single "classification" to which any number of elements can belong (in your case, it's basket-button-inner). That's what they have in common: they're all buttons that are members of that particular classification; they just happen to display on mobile and desktop. An ID is a unique thing to which one and only one element can belong. That's it. If you use an ID, you're saying "I expect there to be only one of these things because it's so unique I gave it an ID."

Generally speaking, you'll want to be reserved in giving things IDs. Things deserving of IDs include stuff that's really important, like an element you're going to refer to in a script; or an element from which you want to create a new styling context as IDs are very powerful, very specific selectors that are hard to override)