CSS specificity problem
I'm working on creating a javascript game for my own education. The game requires several pages, which I'm implementing through hidden div
s that get hidden/unhidden when you want to view them (offtopic: Any advice about whether or not that's a good idea is welcome).
I have a CSS rule that hides all of my divs with display: none;
开发者_运维问答 and then a class that unhides a specific div with display:block;
. However, instead of the class unhiding, it seems that my css selector for selecting all the divs is overriding the class, resulting in the rule not applying. I know I can just use the !important
property to fix this, but I want to understand why what I've written doesn't work. I thought that a class would be a specific enough selector, and the rule even comes after the hiding rules.
Here's my source:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" charset="utf-8">
</head>
<body>
<div id="game">
<div id="content">
<div id="viewport">
<div id="home_page" class="current_page">Home</div>
<div id="work_page">Work</div>
</div>
</div>
</div>
</body>
</html>
and css:
#content
{
background: #eef;
padding: 5px;
}
#viewport div
{
display:none;
}
.current_page
{
display:block;
//display:block !important; //One solution, but not preferred
}
#viewport div
is an ID selector and a type selector. That's more specific than .current_page
, a class selector by itself, because of the ID alone.
Instead of applying display: block !important;
, you can and should modify your last selector, giving it the ID so it becomes #viewport .current_page
. This makes the IDs equally specific, with the class selector being more specific than the type selector.
Does this work?
#viewport div.current_page
{
display:block;
/* display:block !important; //One solution, but not preferred */
}
Try with
#viewport #home_page {
display:block;
}
You need to increase specificity, because the use of classes, IDs or nested elements in the CSS rules selector increase specificity by different amounts.
Here is a nice and easy to follow article about CSS Specificity.
As a general rule, I would say that if you need to use the !important
statement, probably you didn't use the right CSS selector. I sometime found myself using the !important
statement just to realize later on that I could obtain the same result using a better selector.
IDs carry more weight than classes, so use
#viewport div.current_page
In addition to the methods provided in other answers, you can also place the display:none
style inline. Most javascript libraries have a show()/hide()
methods - these methods typically change the display
CSS property to block
or none
, respectively. This seems to be the most easy-to-maintain method, and then you don't even have to consider CSS cascades or specificity at all - inline styles trump everything else.
<div id="viewport">
<div id="home_page" class="viewportPage">Home</div>
<div id="work_page" class="viewportPage" style="display:none;">Work</div>
</div>
Javascript:
function handlePageShow (page_element_to_show) {
// hide all pages
var pages = document.getElementsByClassName('viewportPage');
var page_count = pages.length;
for (var i = 0; x < page_count; i++) {
pages[i].style.display = 'none';
}
// now show the target page
page_element_to_show.styles.display = '';
}
This is made even easier using a javascript library such as mootools or jQuery. I wouldn't go add the framework just to accomplish this, but if you're making a game you're going to run in to a couple more instances where a library will make your life easier. In this case... getElementsByClassName
is not available in IE, so you'd have to sub in an implementation of it for IE users. This is one trivial example of the headaches involved in writing complex javascript that works in all browsers.
精彩评论