Understanding CSS sprites and links - css

I have been researching how to use CSS sprites as image links, but I can't figure this out. I have a PNG (here: ) that has two images in it (for simplicity). I want each image to be act as an icon that can be linked to an external website (Twitter and Facebook). I set up my CSS like this:
CSS
#authorpage-links ul {
list-style-type:none;
}
#authorpage-links ul li {
background: url("/links-authorpage1.png") no-repeat scroll 0 0 transparent;
}
#authorpage-links ul li.twitter {
background: url("/links-authorpage1.png") no-repeat 0 0;
width: 20px;
height: 14px;
}
#authorpage-links ul li.facebook {
background: url("/links-authorpage1.png") no-repeat -21px 0;
width: 14px;
height: 14px;
}
...and my HTML like this:
HTML
<ul id="authorpage-links">
<li id="authorpage-links" class="twitter">
<a target="_blank" href="http://twitter.com/"></a>
</li>
<li id="authorpage-links" class="facebook">
<a target="_blank" href="http://facebook.com/"></a>
</li>
</ul>
Now, 2 questions:
1) Is using a list to display these images the best way or should I use div's?
2) Is this an issue with my CSS IDs and classes?
Any help is greatly appreciated.

Based on a revision of your CSS (problems that I'll come to, later) to the following:
#authorpage-list {
list-style-type: none;
}
#authorpage-list li {
float: left;
}
#authorpage-list li a {
background-color: transparent; /* I broke the background down into individual parts */
background-image: url(http://i.stack.imgur.com/ta3Va.png);
background-position: 0 0;
background-repeat: no-repeat;
width: 15px;
height: 15px;
display: block; /* in order that the a elements could be assigned a width/height */
border: 1px solid #f90; /* for diagnostic purposes while working on this, adjust to taste */
}
#authorpage-list #authorpage-facebook-link a {
/* a specific selector, in order to be more specific than the previous
selector which styled the defaults for the a elements in this position */
background-position: -21px 0;
}​
And amending your HTML to the following:
<ul id="authorpage-list">
<li id="authorpage-twitter-link" class="twitter">
<a target="_blank" href="http://twitter.com/"></a>
</li>
<li id="authorpage-facebook-link" class="facebook">
<a target="_blank" href="http://facebook.com/"></a>
</li>
</ul>
I came up with this: JS Fiddle demo.
​
CSS problems
This is the biggest no-no insofar as HTML goes (or so far as I've ever been able to see, it's even worse than the blink tag): you have multiple examples of the same id in your HTML. An id must be unique within the document. If not, you have invalid HTML. Which causes problems with CSS, with JavaScript and...it's just bad.
If you have multiple elements that need to share a property/style, or whatever, use a class, not an id.
Your selectors. #authorpage-links ul should match a ul element within an ancestor element of id="#authorpage-links". The ul is the element with that id. I'll ignore that its child elements also had that id, since I think I've covered that part. All your other CSS started off that base, which wasn't accurate, and so didn't work.

Your <li> elements may be sized to 14x14, but you've got nothing in the <a> tags, so those'll shrink down to a 0x0 area, effectively making your list elements clickable areas invisible. You should probably put a space into the anchor tag, so there's SOMETHING to push them open, e.g.
<a target="_blank" href="http://facebook.com/"> </a>
^^^^^^

Your a link need to have a size. I did so in making the a's have a clickable area. Since your lis don't need a size i gave the size to the a links.
Replace your li css with:
ul#authorpage-links li a {
display: inline-block;
background: url("/links-authorpage1.png") no-repeat scroll 0 0 transparent;
}
ul#authorpage-links li.twitter a {
background-position: 0 0;
width: 20px;
height: 14px;
}
ul#authorpage-links li.facebook a {
background-position -21px 0;
width: 14px;
height: 14px;
}
Also remove the id attribute from your lis.
"... fantastic answer ..." - Sparky672

Related

How can I vertically align a list item marker

I'm trying to increase the size of my list item markers with the following CSS:
li::marker {
color: grey;
font-size: 3.5rem;
}
<ul>
<li>Hello</li>
<li>Gromit</li>
</ul>
The resize works perfectly, but the markers are no longer aligned vertically with the list item contents.
I tried using vertical-align, but I can't seem to get the desired result:
li {
vertical-align: middle;
}
li::marker {
color: grey;
font-size: 3.5rem;
vertical-align: middle;
}
<ul>
<li>Hello</li>
<li>Gromit</li>
</ul>
I tried using position: absolute on the marker to move it. I also tried transform: translateY(x);, but I can't get either to move the marker at all for some reason… Plus I would hate to have to go back and fiddle with x every time I change the font size of the list item or marker.
Here is one of my attempts as an example:
li::marker {
color: grey;
font-size: 3.5rem;
transform: translateY(1000rem);
}
<ul>
<li>Hello</li>
<li>Gromit</li>
</ul>
I've seen a lot of similar questions, but none of them seem to provide a solution which:
Doesn't introduce extra HTML markup
Doesn't introduce custom values that would need to change if the font size of the list item (or that of the marker) changes.
Doesn't require JavaScript
That being said, if I missed something, feel free to point me in the right direction and I will mark this as a duplicate myself.
Frankly, I wouldn't use marker as your styling options are deliberately restricted. Use before instead
Only certain CSS properties can be used in a rule with ::marker as a selector:
All font properties
The white-space property, color, text-combine-upright, unicode-bidi and direction properties & The content property
li {
display: flex;
align-items: center;
padding: .5rem;
border: 1px solid red;
}
li::before {
content: "";
width: 1rem;
height: 1rem;
border-radius: 50%;
background: grey;
margin-right: .5rem;
}
<ul>
<li>Hello</li>
<li>Gromit</li>
</ul>
The before pseudo element solution can give you what you want (and personally it's what I'd use) but in case it is of use to others who for some reason are constrained to using marker, it is possible to set the content to a Unicode large circle as in this snippet and color it.
li::marker {
content: '\2B24 ';
color: gray;
}
<ul>
<li>Hello</li>
<li>Gromit</li>
</ul>
Note: tested OK on Chrome/Edge and Firefox on Windows 10. However, Safari on an iPad IOS (14) is showing a smaller circle.
Add ::before with css:
content: "";
display: inline-block;
vertical-align: middle;

Display second <span> element in front of first

I'm trying to get a second sibling element displaying in front of the first - with some severe restrictions:
I cannot alter the HTML or use javascript or jQuery.
I can only use CSS.
I can't change how classes are assigned (again, I don't have access to change any code apart from the one bespoke CSS file).
The left-hand menu features a number of the above HTML structures, building a clickable menu for the sections on the page. When a page section is completed, the 'completed-section' class is added to the first span (as shown above). This is what is causing me problems:
The CSS styling of the nav-link 'button' should change when it's completed, but since I can't access the parent of a CSS-selected element I need to make these changes directly to the 'menu-number' span element, including a 'nav-link' sized background colour. So I've made the menu-number the same size as the containing 'nav-link' . But when I add a background colour to the 'menu-number' , the text in the second is obscured.
How can I 'move' the second span in front of the first so I can see its text?
I have also tried making both spans position absolute or position relative and used z-index but this pulls the spans out of the flow of the document and means the width of the menu collapses. I can't set the width to a hard-coded value because the menu toggles open and closed, width-wise, (without a class being set) and the toggled width is set by javascript which, again, I can't access.
I have also tried using display: flex on the 'a' element and reversing the 'order' of span elements. No luck.
In semi-desperation I have tried setting the direction property on 'nav-link' to rtl. No luck.
I think I've tried a couple other things too, but at this point I'll wrap this question up.
Any pointers, much appreciated...
.menu-number {
border: none;
border-left: 10px solid transparent;
border-radius: 0px;
padding-top: 13px;
padding-left: 20px;
height: 45px;
position: absolute;
width: 100%;
text-align: left;
z-index: 100;
float: left;
}
.menu-number + span {
/*position: absolute;*/
padding-left: 40px;
z-index: 200;
}
.completed-section {
color: #42bb76 !important;
border-left: 10px solid #42bb76;
background-color: #274d56;
text-decoration: underline;
}
.nav-link > div > a {
display: flex;
*/flex-direction: row-reverse;*/
}
.nav-link > div > a > span:nth-of-type(1) {
order: 2;
}
.nav-link > div > a > span:nth-of-type(2) {
order: 1;
}
.nav-link > div > a > .section-name {
color: white;
padding: 13px 20px 0px 60px;
height: 45px;
float: left;
}
<div class="nav-link">
<div>
<a href="scroll/to/section">
<span class="menu-number completed-section">1.</span>
<span class="section-name">Section name</span>
</a>
</div>
</div>
I've also tried 'flex-direction' but I've now commented that out.
You can achieve this using CSS order property:
Here is the fiddle:
.menu-number {
order: 2;
}
.section-name {
order: 1;
}
.nav-link a{
display: flex;
}
<div class="nav-link">
<div>
<a href="scroll/to/section">
<span class="menu-number completed-section">1.</span>
<span class="section-name">Section name</span>
</a>
</div>
</div>

Why am I getting white space between my HTML element?

I'm trying to design a website for my mums backpackers business. The problem that I am having is between my banner image and my navbar there is a blank white line that you can see in the image. I thought this is to do with the margin so I have set it to zero for both of the elements to no avail.
Also a second question - Why does my black border not cover the main content as well? I thought since its a body background it would go around every element in the body.
I realise there may have been similar questions but I can't find the answer anywhere. I will appreciate anyones input - this is my first post here so I'm sorry if I screwed up any formatting.
The image of my website can be found here:
http://postimage.org/image/20dhjcdb8/
Thanks in advance.
I currently have the following code in my index.html file:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="swaggersstyle.css">
<title>Oamaru Backpackers Hostel, Swaggers Backpackers - Home</title>
</head>
<body>
<img src="final.jpg" id="banner"></img>
<ul id="nav">
<li class="links">Home</li>
<li class="links">Planning</li>
<li class="links">Construction</li>
<li class="links">Evaluation</li>
</ul>
<div id="mainc">
<p>Make Yourself at Home</p>
<p>Swaggers Backpackers is a converted old house located within walking distance of all the best parts of Oamaru. Explore the old victorian era buildings and shops of the city centre, or see the penguin colonies down the street. Swaggers is owned and operated by camp mum Agra, who makes all guests feel welcome, informed, and perhaps a bit mothered. </p>
</div>
</body>
</html>
and the following CSS code:
html{
font-family: sans-serif;
background-color:#464E54;
}
body{
width: 960px;
margin: auto;
background-color: white;
border: 5px solid black;
}
#banner{
padding: 0px;
margin: 0;
}
#nav {
list-style-type: none;
padding: 0px;
margin: 0px;
overflow: hidden;
}
#mainc {
width: 960px;
float: right;
background-color: white;
margin: 0;
}
.links {
float: left;
margin: 0px;
}
a:link, a:visited {
display: block;
width: 232px;
font-weight: bold;
color: grey;
background-color: #dad8bf;
text-align: center;
padding: 4px;
text-decoration: none;
text-transform: uppercase;
margin-top: 0px;
}
a:hover, a:active{
background-color: #333333;
}
The problem that I am having is between my banner image and my navbar there is a blank white line that you can see in the image. I thought this is to do with the margin so I have set it to zero for both of the elements to no avail.
In HTML images are by default inline level elements so they follow text rules (and will have blank space below to keep the correct alignment with letters like "p" and such). You can either assign display: block to the header image, or define the header container to have the same exact height as the image
Also a second question - Why does my black border not cover the main content as well? I thought since its a body background it would go around every element in the body.
Because floated elements pop out of their container, you have to clear the float to extend the container with something like
<div style="clear: both"></div>
or use some reset/clearfix css such as the one provided by html5boilerplate.
add to your css
#banner { display: block; }
If you remove the float property of #mainc then the border will surround all the content. By using float, you are taking the div out of the main page flow.

CSS - removing horizontal space in list menu using display: inline property

I'm new to CSS and have a set target of learning & publishing my website in CSS by the end of the month.
My question:
I'm trying to build a CSS horizontal menu with hover drop downs, however, when I use the display: inline property with li (list) items, I get horizontal spaces between the li (list) items in the bar. How do I remove this space?
Here is the HTML:
<div id="tabas_menu">
<ul>
<li id="tabBut0" class="tabBut">Overview</li>
<li id="tabBut1" class="tabBut">Collar</li>
<li id="tabBut2" class="tabBut">Sleeves</li>
<li id="tabBut3" class="tabBut">Body</li>
</ul>
</div>
And here is the CSS:
#tabas_menu {
position: absolute;
background: rgb(123,345,567);
top: 110px;
left: 200px;
}
ul#tabas_menu {
padding: 0;
margin: 0;
}
.tabBut {
display: inline;
white-space:
list-style: none;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,142,190,1)),to(rgba(188,22,93,1)));
background: -moz-linear-gradient(top, rgba(255,142,190,1), rgba(188,22,93,1));
font-family: helvetica, calibri, sans-serif;
font-size: 16px;
font-weight: bold;
line-height: 20px;
text-shadow: 1px 1px 1px rgba(99,99,99,0.5);
-moz-border-radius: 0.3em;
-moz-box-shadow: 0px 0px 2px rgba(0,0,0,0.5);
-webkit-border-radius: 0.3em;
-webkit-box-shadow: 0px 0px 2px rgba(0,0,0,0.5);
padding: 6px 18px;
border: 1px solid rgba(0,0,0,0.4);
margin: 0;
}
I can get the space removed using the float: left/right property but it's bugging me as to why I cannot achieve the same effect by just using the display property.
I had a remarkably similar question a couple weeks ago.
The horizontal spaces are perfectly reasonable. Between inline elements, whitespace matters. This makes perfect sense when you consider the following markup under generic styles:
<b>Label:</b> <span>content</span>
Wouldn't you feel frustrated if this content rendered as the following?
Label:content
The prevalence of block elements in HTML spoils us into forgetting about the role of whitespace. But we must remember that whenever using inline elements (including inline-block elements), that whitespace in the markup actually does matter since HTML is fundamentally a markup and not a coding language.
There a a few solutions to your problem (assuming you want to hold onto the whitespace in the HTML for aesthetic reasons—if this is not important, just remove the space and be done with it), the easiest of which is to apply font-size: 0px to the parent container and then restore the font size to font-size: 16px or whatever it is in each of the inline elements. This makes it so that the text nodes between them have a font size of zero.
The problem is some browsers will render the white space between list items. For example:
<li>item 1</li>
<li>item 2</li>
There is a newline (and probably some tabs) after the </li> on the first line and before the <li> on the next line. Some web browsers will render this as a space. There are two workarounds.
One is to remove all these spaces, like so:
<ul>
<li id="tabBut0" class="tabBut">Overview</li><li id="tabBut1" class="tabBut">Collar</li><li id="tabBut2" class="tabBut">Sleeves</li><li id="tabBut3" class="tabBut">Body</li>
</ul>
This is a kind of ugly solution, but it works.
The other possibility is what you mentioned yourself -- use float: left. Personally, I always go with the float solution.
Using float:left complicates the layout calculation for browsers. If you care about rendering speed and efficiency, remove all whitespace between the <li> items.
<html>
<head>
<style>
ul li, ul li:before,ul li:after{display:inline; content:' '; }
</style>
</head>
<body>
<ul><li>one</li><li>two</li><li>three</li></ul>
<ul>
<li>one</li>
<li>tw`enter code here`o</li>
<li>three</li>
</ul>
</body>
</html>

Best Image Replacement Technique

What is the best (as in cross-browser) technique to do image replacement in CSS? I am using sprites to do my navigation, but I want the markup to remain SEO friendly. Given the following HTML structure...
<div id="menu">
<ul>
<li>Test</li>
<li>Tester</li>
<li>Testing Testing</li>
</ul>
</div>
What is the best way to replace the text with a background image using CSS only?
I am currently using this...
text-indent: -9999px;
But, it fails with CSS on, and images off.
If this is the html:
<div id="menu">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
And this is the css:
#menu ul li a{
display: block;
overflow: hidden;
text-indent: -9999px;
background: transparent url(yourpicture.png) no-repeat 0 0;
width: 100px;
}
#home{
background-position: 0px 0px
}
#about{
background-position: -100px 0px
}
#contact{
background-position: -200px 0px
}
The image would then be 300px wide, and each tab would be 100px wide.
In 2008, Google's presentation at An Event Apart made it clear that valid image replacement will not be penalized by Google. See Mezzoblue's post about it
Basically, as long as the image you replace the text with has the same text in it, it will be considered valid and not trying to cheat search engines. How do they determine whether the image is valid or not? I have no idea... OCR? Manual review?
As far as CSS on/images off, there is no perfect solution, all of them require extra non-semantic markup. See the css-tricks link that beggs posted on the different techniques. I personally do not bother with the very small percentage of users who browse with CSS but no images.
Your choice is simple. Extra markup, or don't care about css on/images off.
The background image is usally applied to the <a> link, giving the entire clickable area an image. To hide the text you can use a very big negative value for text-indent.
I just came up with this, it seems to work in all modern browsers, I just tested it then on (IE8/compatibility, Chrome, Safari, Moz)
HTML
<img id="my_image" alt="my text" src="images/small_transparent.gif" />
CSS
#my_image{
background-image:url('images/my_image.png');
width:100px;
height:100px;}
Pro's:
image alt text is best-practice for accessibility/seo
no extra HTML markup, and the css is pretty minimal too
gets around the css on/images off issue where "text-indent" techniques still hide text for low bandwidth users
The biggest disadvantage that I can think of is the css off/images on situation, because you'll only send a transparent gif.
It might be possible to write a little javascript to help out with this, replacing all the image sources with their background-image css properties. But this would only work if the browsers still attaches css properties to elements and then ignores them. I don't know if this is the case or not, I'll have to test it out. You'd also want to develop a javascript-based test to see if css is being applied to the page (maybe check the position of some test element).
btw, I'd like to know, who uses images without stylesheets? some kind of mobile phone or something?
edit:
Based on comment below... inline styles hrm... maybe I should just make a php helper function like <?php echo css_image('image_id','my text','image_url');?> to generate some code like this:
HTML
<div id="image_id" style="background-image:url('image_url')" class="image">
<img src="image_url" class="alt_text" alt="my text" />
<p>my text</p>
</div><!--/#my_image-->
then just attach some CSS in the stylesheet
#image_id{width:*image width*;height:*image height*}
.alt_text{position:absolute;top:0px;left:0px}
.image{display:block;background-position:left top}
.image p{position:absolute;left:-9999em}
it's an older technique that I'm using, not sure where I found it though. It works with CSS on/images off, CSS off/images on, CSS on/images on.
If a user with CSS off/images off visits, they'll see doubled up text. If a search engine spider visits, they'll see alt text and regular text, an intelligent spider could easily identify this for what it is, an innocent image replacement technique.
So, this technique is worst for screen readers, since alt text is read, but these users should be able to skip to the next paragraph, which is why I stuck <p></p> around "my text".
Everyone else with both CSS and images turned off is some kind of bot, right?
#menu ul li a {
display: block;
background-image: url(images/someimage.png);
text-indent: -9000px;
width: 454px;
height: 64px;
}
The display:block is important or else your width and height may not look right.
This is the code I use for replacing logo text with an image while keeping the text in the code but not shown to the user (this is Google approved). View the completed example here:
http://discretiondesigns.com/overflow/imagereplacement/
Here's the full code (images can be found at the above link - images can be varying sizes - the entire image is clickable and changes upon hover):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Image Replacement</title>
<style type="text/css">
<!--
#menu li { list-style: none; }
#menu #a { font: .9em Verdana, Arial, Helvetica, sans-serif; color: #E9E7E0; height: 20px; width: 100px; padding-top: 8px; padding-left: 8px; float: left; }
#menu #a a { background: url(http://discretiondesigns.com/overflow/imagereplacement/a_off.gif) no-repeat left top; height: 20px; width: 100px; display: block; }
#menu #a a:hover { background: url(http://discretiondesigns.com/overflow/imagereplacement/a_on.gif); }
#menu #a span { display: none; }
#menu #b { font: .9em Verdana, Arial, Helvetica, sans-serif; color: #E9E7E0; height: 20px; width: 100px; padding-top: 8px; padding-left: 8px; float: left; }
#menu #b a { background: url(http://discretiondesigns.com/overflow/imagereplacement/b_off.gif) no-repeat left top; height: 20px; width: 100px; display: block; }
#menu #b a:hover { background: url(http://discretiondesigns.com/overflow/imagereplacement/b_on.gif); }
#menu #b span { display: none; }
#menu #c { font: .9em Verdana, Arial, Helvetica, sans-serif; color: #E9E7E0; height: 20px; width: 100px; padding-top: 8px; padding-left: 8px; float: left; }
#menu #c a { background: url(http://discretiondesigns.com/overflow/imagereplacement/c_off.gif) no-repeat left top; height: 20px; width: 100px; display: block; }
#menu #c a:hover { background: url(http://discretiondesigns.com/overflow/imagereplacement/c_on.gif); }
#menu #c span { display: none; }
-->
</style>
</head>
<body>
<div id="menu">
<ul>
<li id="a"><span>Nav A</span></li>
<li id="b"><span>Nav B</span></li>
<li id="c"><span>Nav C</span></li>
</ul>
</div>
</body>
</html>
This is touted to work no matter the settings of css/images:
http://www.tjkdesign.com/articles/tip.asp
CSS Tricks has one of the most detailed posts on the subject here
They show various techniques. The one that solves your problem of css on and images off is:
HTML:
CSS Tricks has one of the most detailed pages on the subject here
They show various techniques. The one that solves your problem of css on and images off is the technique #8:
HTML:
<div id="menu">
<ul>
<li><span></span>Test</li>
<li><span></span>Tester</li>
</ul>
</div>
CSS:
#menu a {
width: 350px; height: 75px; /*your values here*/
position: relative;
}
#menu a span {
background: url("images/li.jpg"); /*your image here*/
position: absolute;
width: 100%;
height: 100%;
}
EDIT: Updated the code to the sample provided.
PS: I didn't test the code above.
CSS:
#menu ul li a{
display: block;
background-image: url(http://example.com/sprite.png);
width: 100px;
height: 50px;
}
#a {
background-position: <offset for sprite>;
}
#b {
background-position: <offset for sprite>;
}
#c {
background-position: <offset for sprite>;
}
HTML:
<div id="menu">
<ul>
<li id="a">Test</li>
<li id="b">Tester</li>
<li id="c">Testing Testing</li>
</ul>
</div>
Edit: added the link text back in... 'cause it was missed. :-)

Resources