homepage Welcome to WebmasterWorld Guest from 54.167.173.250
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / CSS
Forum Library, Charter, Moderators: not2easy

CSS Forum

    
Create a graphical button with img and text?
Bram




msg:3797180
 11:18 pm on Nov 30, 2008 (gmt 0)

I'm trying to create a graphical button with custom images and text on it. My approach was to split the generic button image into 3 parts:

(since I can't seem to post images here (?) here are links to the 3 images) <snip>

Then create a borderless table with these images as background, and put the desired content (text and/or images such as this random <snip>) in the middle.

Below is what I got so far. Three questions:

  1. Am I on the right track, or should I do this completely differently? (e.g. no tables at all, and just div/span or something?)
  2. On Firefox and Opera, it looks OK. On IE6, there's two white bars in the button. How do I fix that?
  3. Is there a way to not make the table break to a new line? I.e. could I put this button thing somewhere between regular text?

Thanks a lot in advance!

Here's my current HTML:

---------------------------------------------

<html><head>

<style type="text/css">
<!--
a { text-decoration: none; }
table { border-spacing: 0; }
td.ButtonMain { vertical-align: center; font-family: Arial; font-weight: bold; color: #ffffff; }
img.ButtonImg { border: 0; vertical-align: middle; }
-->
</style>

</head>
<body text='#000000' bgcolor='#ffffff'>

<a href='some/other/page'>
<table><tr class='ButtonRow' height='68px'>
<td background='button_left.gif' width='36px'></td>
<td background='button_middle.gif' class='ButtonMain'>

<img src='icon.gif' class='ButtonImg'> Click here for something wonderful to happen!

</td>
<td background='button_right.gif' width='36px'></td>
</tr></table>
</a>

</body></html>

[edited by: swa66 at 12:36 am (utc) on Dec. 1, 2008]
[edit reason] No personal URLs, please see forum charter [/edit]

 

coaster01




msg:3798044
 5:57 am on Dec 2, 2008 (gmt 0)

It's hard to say, not seeing your images, but it sounds like what you want to do isn't that hard in CSS.

<div class="bg-bottom-img">

<div class="bg-middle-img">

<div class="bg-img-button-box">

<a href="link" alt="descrip"><img src="button" />text</a>

</div>

</div>

</div>

I don't know, maybe I'm not getting the real picture of what you want to do. That's a lot of server activity, loading and rendering. Do these images change? If not, can you combine them into one image? In fact, if you want to study what they call "rollover images" you can combine all your images into one file and just using CSS background positioning to get the right background in the right box.

Sources of CSS problems: do you know that Firefox/Safari/Chrome/Opera/IE7 and that nasty little rascal IE6 interpret your CSS differently? It took me months to get that straight. I'd have been better off to thoroughly learn and understand the "box model" and how IE6 renders its boxes differently than the other browsers do. The other important concept that tripped me up is which elements are block elements and which are line elements, and what that means with respect to "breaking to new lines."

Sorry if this is all obvious; stuff you know already; I'm new here myself. Not all your post made it through editing. ;-)

swa66




msg:3798146
 10:38 am on Dec 2, 2008 (gmt 0)

1. Am I on the right track, or should I do this completely differently? (e.g. no tables at all, and just div/span or something?)

I'd not use tables at all unless I have tabular data to render.
Basically the thing is simple suppose you're explaining it on a white board, do you draw a grid: go for a table, if not: no table.

But ... I'd also be careful not to fall into the trap (yes it is a trap) of replacing the table markup with dozens of divs and sans either.

Try to make the html on itself to have sense. Screen readers, search engines, and all those browsers you have no chance of testing with (I don't own every possible phone, every possible game console, every possible settop box, fridge and whatnot they'l put a browser in in the future) will like it better.

2. On Firefox and Opera, it looks OK. On IE6, there's two white bars in the button. How do I fix that?

I might be mistaken, but it sounds like you're building it using IE7. Thats actually a bad idea in the long run. The problem is that sooner rather than later you'll run into a case where IE7 does things different just as IE6 is doing in your case and then it becomes hard to fix it. The easier path is to do everything in one of the standards compliant browsers (FF, safari, opera, ... take our pick (I prefer FF as it has some add-ons I really like (web developer toolbar and firebug). Every so often take a quick glance at what the other standards compliant browsers are makign of it, but stay away from IE, it'll only put you on the wrong foot.

When it's done in the standards compliant browsers, I make a point of not editign the main CSS any longer (prevents IE8 -promised to be standards compliant as well, from being triggered by the workarounds for the old versions of IE)

TO fix those old versions of IE: use conditional comments: it prevents you from needed to recheck the stuff you add to make IE behave from interfering with all the other browsers already tested and confirmed to be good. It also allwos you to just make it work without worrying that some unable to test browser might throw a fit over it.

3. Is there a way to not make the table break to a new line? I.e. could I put this button thing somewhere between regular text?

I guess, but I never tied it (since I'm not using tables for anything but tables that "display:inline-table" would do it if you read the standard, but support from browsers might be below par.

That still doesn't give you an example of how some of us make buttons.

But you'll need to read up on a bit of technique first:

  • Some of the things we often use is a technique called "sliding windows". Basically there are two portions of a background that are brought to sit on top of each-other each bringing in one side of the graphic. It can be done vertically as well as horizontally, and even in both directions at the same time.
  • The next one is CSS sprites: basically we merge multiple images into a larger one and position our background to show the part we need. This is about the opposite technique of what slicing is in a the table layout world.

For menus it's common to have sliding windows on the <li><a>...</a></li> by having one part of the background on the <li> and one on the <a>, you can basically choose the right or the left one to be on either, but the <a> will always show the largest part, the <li> will just show the "cap".

In your case the ideal "clean" html would be something like:

<p>this is a <a href="#">button</a> as link</p>

but it lacks the second element to use for what the <li> is used above.
So one (obvious) solutions is that you could add a span around the <a> and use that. It's relatively easy to get it going. Take a look at
[webmasterworld.com...] if you want to go that way as it does sliding doors on inline text (it crates a menu, so there's some work left, but most of what you need is in that example).

Now adding html is something I like to avoid. CSS3 will give us multiple backgrounds on a single element, but that's not here just yet. a :before or a :after however might do the trick. (although IE will not want to play nice).

swa66




msg:3798247
 2:50 pm on Dec 2, 2008 (gmt 0)

I've been playing with the "don't add to the html" a bit more.

I started with:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
</head>
<body>
<p>this text goes before the link</p>
<p>this is a <a href="#">button</a> as link</p>
<p>this text goes after the link</p>
</body>
</html>

So let's get some background and that :before going (in a standards compliant browser, IE won't cooperate just yet in any way or shape).
Whiel at it, add some padding to the left of the :before and similarly some on teright of the a as well as some on top and bottom of both the a and the a:before (so there is space for that border

a {
background-color:red;
text-decoration:none;
color:inherit;
padding: 5px 10px 4px 0;
}
a:before {
background-color:green;
content: "";
padding: 5px 0 4px 10px;
}

Doesn't look that bad, but let's give the paragraphs a bit more spacing so we can add a border without it running into other text.

Since we want the text to fit in a fixed height background image, we'll need to nail it down too.

p {
font-size: 14px;
line-height: 23px;
}

Test it in the other standards compliant browsers we can get our hands on while the background colors are still there.

It looks kinda Ok, in safari and opera, but the height isn't pixel perfectly the same, so we'll need to see how much difference it is and make our image a but flexible as it'll be hard to fix the height further without getting rid of the inline aspect.

Still on to IE .. IE <8 doesn't support :before, so we're toast unless we add scripting support to it

<!--[if lt IE 8]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js"
type="text/javascript"></script>
<![endif]-->

Uh? Where's the green background?
Maybe it doesn't like it that the :before is empty

<!--[if lt IE 8]>
<style type="text/css">
a:before {
content: " ";
}
</style>
<![endif]-->

adds a space as content, let's try that.

Works, but now the green box is too big (to be expected). And the red one, well it get's expanded by the padding on the :before, so we can get rid of the vertical padding on the <a> for IE

After some fiddling to get the same in width as in other browsers:

<!--[if lt IE 8]>
<style type="text/css">
a {
padding: 0 10px 0 0;
}
a:before {
padding: 5px 0 4px 6px;
content: " ";
}
</style>
<![endif]-->

Sounds about good.

Next back to having all the browser windows next to one another and check the height of the colored blocks:

On my display, from tallest to lowest: safari, IE6 & 7, firefox, opera
yet the total is probably just a few pixels, something we should be able to handle in the image we now need to create

Let's create an image:
1024px by 30px
containing a graphical button vertically centered on it with a top and bottom standing 4 px away from the border (I added temporary measuring bots in colors on it to see where it ends up in the block)

Adding them:

a:before {
background: url('test.png') no-repeat center left;
}
a {
background: url('test.png') no-repeat center right;
}

Looking at the measuring dots I had on there:
FF: 1px at top 1px at bottom
Safari: 2px at top and bottom
Opera: 0px at bottom, 1px at top
IE6&7: 1px at top, 2px at bottom
showing of the margin in the image

So that's pretty close (considering they're not all using the same font etc.)

Adding it together:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
a {
background: url('test.png') no-repeat center right;
text-decoration:none;
color:inherit;
padding: 5px 10px 4px 0;
}
a:before {
background: url('test.png') no-repeat center left;
padding: 5px 0 4px 10px;
content: "";
}
p {
font-size: 14px;
line-height: 23px;
}
</style>
<!--[if lt IE 8]>
<style type="text/css">
a {
padding: 0 10px 0 0;
}
a:before {
padding: 5px 0 4px 6px;
content: " ";
}
</style>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js"
type="text/javascript"></script>
<![endif]-->
</head>
<body>
<p>this text goes before the link</p>
<p>this is a <a href="#">button</a> as link</p>
<p>this text goes after the link</p>
</body>
</html>

Hope this inspires some of you.

coaster01




msg:3798282
 3:35 pm on Dec 2, 2008 (gmt 0)

Excellent tutorial from someone who's obviously well-versed and professional. The only difference I'd have, is that I've tried to code my html without any conditionals making exceptions for non-compliant browsers, and I've been able to do that (but it wasn't easy). Why? Because Microsoft will come out with a new browser and then are we going to have to recode all the conditionals in our html?

So, I'm just wondering if, and I know this is asking an awful lot after all the time and effort he's put into composing that excellent response, if there's a way he can suggest to do the same WITHOUT conditionals?

Thanks......always trying to learn! ;-)

swa66




msg:3798306
 4:21 pm on Dec 2, 2008 (gmt 0)

Actually the reason to use the conditional comment is to prevent the workarounds to be given to IE8 (which is promised to be standards compliant).

I just tested it in the virtual machine that's been upgraded to IE8beta2: works as expected (with it being excluded from the conditional comment).

All that you need to change is once the IE6 and IE7 usage drops below the "I don't care anymore" percentage, is to deleted everything in the conditional comment. By then you can probably work on using CSS3.

I strongly believe we need to move all 'needed for IE' stuff into a conditional comment instead of the reverse. I tried to explain it here: [webmasterworld.com...]

The cheating I did include in here is to use IE8.js to upgrade some of the abilities of IE (a.o. to support :before).

coaster01




msg:3798432
 7:15 pm on Dec 2, 2008 (gmt 0)

I don't know yet how to use any quoting features you have here so this is from the thread swa66 links to:

quote:[It is my firm belief IE6 causes a tremendous amount of extra markup in both html and css that should not be there to begin with, and can only cause trouble down the road.] unquote.

Boy, can I ever relate to that statement! In my case it wasn't necessarily all that much extra markup as it was just a tremendous amount of time wasted futzing about with different CSS to make it work the same across five different browsers.

So, I take it that in the world of professional site designers these days the preferred method of handling different rendering of the box model is to use conditional statements?

What are your thought on using javascript to implement the conditionals instead of IE's html parser?

alt131




msg:3798729
 12:41 am on Dec 3, 2008 (gmt 0)

Hi Bram,
Am I on the right track, or should I do this completely differently? (e.g. no tables at all, and just div/span or something?)

Do it differently! ;)
As you will have figured by now a table inside a link means the link doesn't work. (Or shouldn't). Plus that is a lot of complicated, invalid mark-up that is semantically incorrect as well as additional requests to the server to collect the sliced images that really shouldn't be required.

I am guessing the display differences you see are caused by browsers attempts to interpret invalid code, plus dealing with cellpadding and spacing differently - and possibly "gaps" caused by the image dimensions.

In achieving what you want, the goal is to use the minimum valid css and markup in a way that minimises impact on assistive and alternate devices or user agents. The following is a simple example that requires no javascript or conditional comments. It sets your (re-assembled) generic button image as a background on the <b> - used because you wanted the link text to be bold - but you could equally use <strong> if that was what you actually wanted to convey to assistive devices. The "icon" is set directly on the <a>, and for the sake of the example I have set a further image for a change on hover.

A search on "css buttons" will produce many examples of ways to achieve button effects - including, as other posters have suggested, creating a single image and using positioning. That has the great advantage of reducing requests to the server if there will be many of these image links on the page. This however, is a simple example to get you started - dimensions etc will need adjustment for your situation.

Tested in ie6&7, FF2&3, Opera9.2&9.6, winSafari - and just for fun, ie5.5

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>My Button</title>
<style type="text/css">
/*generic reset*/
* {
padding:0;
margin:0;
border:0;
}

p {
font-family: Arial, sans-serif;
font-size:14px;
line-height:30px;
background-color:aqua;
width:300px;
margin:4em auto;
padding:2em;
}

b {
display:inline-block;
width:80px;
line-height:22px;
text-align:center;
vertical-align:middle;
background: green url(button.gif) no-repeat;
padding:4px;
}

b a {
background: blue url(icon.gif) no-repeat;
display:block;
text-decoration:none;
color: #fff;
}

b a:hover {
background: red url(hover.gif) no-repeat;
}
</style>
</head>

<body>
<p>This is a an example of using a <b><a href="go.htm">button</a></b> as a link in a real paragraph that has several lines of text </p>
</body>
</html>

@coaster01
So, I take it that in the world of professional site designers these days the preferred method of handling different rendering of the box model is to use conditional statements?
In my observation many coders start with techniques that avoid rendering differences. Opera can be extraordinarily difficult to deal with. If there is simply no other way to deal with ie (not uncommon if constraints imposed by other factors limit the options for Opera), then current thinking tends towards conditionals rather than hacks. My personal opinion is that if adjustments for ie become so numerous it would be more efficient to create a separate external style sheet for ie, then it is time to review the basic code.

What are your thought on using javascript to implement the conditionals instead of IE's html parser?
I refuse to traumatise myself by thinking about it ;)

IMO it is a return to the days when browsers used proprietary elements and options were so limited many of the things we now take for granted could only be achieved using javascript (which itself had proprietary differences). Aim for valid code that is platform, device and ua independent - "write once use many". Keep things simple to provide less opportunity for things to go wrong. Plus, it is much less risky to tinker server-side than rely on client-side. I never consider javascript these days - to the point I have not used it to achieve a visual display effect in at least 4 years.

[edit]owner edit - grammar[/edit]

[edited by: alt131 at 1:23 am (utc) on Dec. 3, 2008]

coaster01




msg:3798742
 1:00 am on Dec 3, 2008 (gmt 0)

Thank you; good points to ponder. I need to rethink some of my coding on my website. While I have everything rendering the same across the browsers I mentioned earlier, it's at the expense of very slow page loading and rendering, and that's something I'm still struggling with. Taking a whole different approach might be what I have to do.

I'm so impressed with this site and its members so far.

I'm off now to try out your example code. :-D

swa66




msg:3799069
 12:42 pm on Dec 3, 2008 (gmt 0)

If you use the <b> and the <a> you could do sliding windows on them too... it all depends if you want the buttons to scale with content or if you want it to be a fixed size.

Bram




msg:3799806
 8:38 am on Dec 4, 2008 (gmt 0)

Thank you VERY much indeed for all this help! Very useful!

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / CSS
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved