homepage Welcome to WebmasterWorld Guest from 107.21.163.227
register, free tools, login, search, subscribe, help, library, announcements, recent posts, open posts,
Subscribe to WebmasterWorld
Home / Forums Index / Code, Content, and Presentation / CSS
Forum Library, Charter, Moderators: DrDoc

CSS Forum

This 38 message thread spans 2 pages: 38 ( [1] 2 > >     
Unwanted Spaces Between Rows Of Images
icon_kid




msg:4614877
 8:58 pm on Oct 5, 2013 (gmt 0)

For my "Brooklyn Mapping" project there were three obstacles to overcome. The first one was how to do multiple image swaps using check boxes, which was solved by fotiman. The second was how to have two (or more) tables sit side-by-side and be scrollable (though this effect uses plain/unscrollable tables within scrollable DIVs), which was solved by lucy24. The third and last hurtle is to close the 5-pixel space that appears between rows of images.

The following code renders three rows
-- each row has five images.

<nobr>
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
</nobr><br>

<nobr>
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
</nobr><br>

<nobr>
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
</nobr>


A diagramatical representation of how this code renders is this:
(fifteen images arranged in three horizontal rows, however with space between rows
-- even though the default 'VSPACE' around images is supposed to be ZERO.

|******|******|******|******|******|
|******|******|******|******|******|
|******|******|******|******|******|

|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|

|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|

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

By searching the matter I found a tip from one author -- that putting each row in a <DIV> will clap them all together solid.
This is the amended code:
(minus the <br> tags which are not necessary here because the DIVs automatically cause line breaks at their ends):

<div class="row"><nobr>
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
</nobr>
</div>


Terrific! -- the DIVs collapsed the spaces so the rows look like this:

|******|******|******|******|******|
|******|******|******|******|******|
|******|******|******|******|******|
|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|
|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|

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

... but my final problem is this:
The DIVs need to be contained in a table, however, when they are placed within a table they somehow become inate, meaning that they lose whatever power they had to close the gaps between rows, and the 5-pixel spaces return. The code looks like this:

<table>
<tr>
<td>
<div class="row"><nobr>
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
</nobr>
</div>
</td>
</tr>
</table>


...and goes back to looking like this again:

|******|******|******|******|******|
|******|******|******|******|******|
|******|******|******|******|******|

|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|
|#####|#####|#####|#####|#####|

|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|
|@@@@|@@@@|@@@@|@@@@|@@@@|

So my basic question is:

Why do DIVs close gaps between rows when not in a table, but fail to close gaps when placed in a table?
More important to me than why, is: how do I alter the code to force rows of images to always be adjacent?

The suggestion that the FONT SIZE in the document body has something to do with this has already been tested with no effect. Can anyone suggest something else to try?

I placed this post in the CSS Section because I think that the solution will ultimately be a CSS one, but I'm not sure on that.

 

lucy24




msg:4614890
 12:12 am on Oct 6, 2013 (gmt 0)

<div class="row"><nobr>

Tangential, but I gotta say it.

CSS
div.row {white-space: nowrap;}

and then you can get rid of all those <nobr></nobr> tags-- which have been deprecated since about 2001 anyway. The same goes for anything in <font...

What does your current CSS say about
div
and/or
table div
?

As a matter of principle it's a good idea to say generically
table {font-size: inherit; font-family: inherit; line-height: inherit;}
et cetera, just in case a browser gets cranky. In practice, things only get weird in "quirks" mode, but why take chances?

Font size really shouldn't be an issue, since your images are surely taller than a typical row of text in any size you could name.

icon_kid




msg:4614898
 1:38 am on Oct 6, 2013 (gmt 0)

What does your current CSS say about div and/or table div?

I don't have a current CSS -- which is most likely why I have a problem in the first place.

Font size really shouldn't be an issue, since your images are surely taller than a typical row of text in any size you could name.

Actually, the relative size of typical fonts to my images did come into question because they did fall into close range of each other -- because my images are only seventeen pixels tall and some fonts can be taller than that. In another thread regarding this same issue it was your advice that I set my FONT SIZE to something that definitely renders smaller than my images because, as you said [paraphrase]:

If an image is smaller than the font (line height) then an empty space equal to the difference must appear above the image.

For example: if my line height is 20 pixels and my image is 17 pixels then 3 pixels of empty space must appear above the image to match the height of the line. Taking that into consideration I changed the font size to '1' which probably renders at something like ten pixels -- well below the height of my images. Even though my images were now certainly taller than the line height, spaces between rows still appeared.

inherit -- that looks nifty. I'll try this stuff and report on what happens.

Thanks.

icon_kid




msg:4614972
 6:15 pm on Oct 6, 2013 (gmt 0)

I've tried your two suggestions with no effect, which were:

table {font-size: inherit; font-family: inherit; line-height: inherit;}

and

div.row {white-space: nowrap;}

Below is the complete code for a test document. You can test it yourself using a small image which you've named "blank.png."
Five pixels of empty space appears between the three rows of images.

<!DOCTYPE html>

<head>
<title>lucy-5</title>

<script>
table {font-size: inherit; font-family: inherit; line-height: inherit;}
div.row {white-space: nowrap;}
</script>

</head>
<body>

<div style = "width: 600px; overflow: auto; height: 400px;
display: inline-block; background-color: #CDC;">
<table style = "width: 600px; height: 400px; border: 2px solid #82a3d2;
background-color: #C1D2EC;">
<tr>
<td>
<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/></nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/></nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/></nobr>
</div>
</td>

</tr>
</table>
</div>

</body>
</html>


One thing to note is how the IMG tags are written:

/><img src="blank.png"
as opposed to this:
<img src="blank.png">

In one experiment I changed all the tags to the normal way because it looks neater, however, there's a reason why they need to be written this way, which I found out -- when written the normal way, two pixels of empty space is added to the right side of each image. I'm a pixel guy -- and so I checked out a screen grab of the rendered page in an image editor to determine if what I was seeing was one pixel being added to each side of an image, which would give the same impression as two pixels added to one side when images are placed next to each other, and it turns out to be the latter (nothing on the left side but two on the right side). No one needs to explain this because probably no one here knows definitively about it and, since I'll be keeping the IMG tags in the odd form they're in, my only issue is the unwanted vertical spaces, not horizontal space. The distance between rows stayed the same at five pixels which is what I'm trying to get rid of.

swa66




msg:4614989
 9:23 pm on Oct 6, 2013 (gmt 0)

It all boils down to one simple fact: an image is by default an inline element, just like a word of text it sits on a line, allowing space between words (your horizontal gaps) and allowing space for descenders on that line of text (your vertical gaps.

You can change how an image is displayed with the CSS display property.

But you really do not need <nobr>, nor that table.

I honestly don't get why you continue to not want to listen, and refuse to take a step back from the stuff that doesn't work and into a new world.

So if en when you get ready to leave the old world behind:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="UTF-8" />
<title>test</title>
<style>
* {
margin:0;
padding:0;
}
.row {
height: 50px;
overflow:hidden;
}
.cell {
height: 50px;
width: 50px;
float: left;
}
#wrapper {
min-width: 150px;
}
</style>
</head>
<body>
<div id="wrapper">
<div class="row">
<div class="cell" style="background-image: url('img11.png')"></div>
<div class="cell" style="background-image: url('img12.png')"></div>
<div class="cell" style="background-image: url('img13.png')"></div>
</div>
<div class="row">
<div class="cell" style="background-image: url('img21.png')"></div>
<div class="cell" style="background-image: url('img22.png')"></div>
<div class="cell" style="background-image: url('img23.png')"></div>
</div>
<div class="row">
<div class="cell" style="background-image: url('img31.png')"></div>
<div class="cell" style="background-image: url('img32.png')"></div>
<div class="cell" style="background-image: url('img33.png')"></div>
</div>
</div>
</body>
</html>>


At assumes your cells are 50px by 50px, but thats an easy change.
The elements I position are all divs, and contain NOTHING.
All the images are drawn on the cells as a background image.

There's just 3 simple CSS statements in there: it sets the hight of the rows, the size of the cells and sorts the cells left-right into the rows. The final one makes sure the wrapper is wide enough to hold a row (if you don;t do that the floats will still wrap).

The style on the "cell" divs are using inline overrides to set their individual background images.

Now this works, no spaces, but there's a bunch of similar ways to do the same.

Oh FWIW: that's polyglot html5, should be served as xml to supporting browsers, but it'll work just fine if you serve it as html to try it out (it's not important to get this working, just that I don't do non-polyglot html5 anymore).

swa66




msg:4614990
 9:26 pm on Oct 6, 2013 (gmt 0)

Oh before I forget: tiling an image isn't quite useful anymore... A modern browser will only download 2 at once.

lucy24




msg:4614992
 9:32 pm on Oct 6, 2013 (gmt 0)

Whoops! Overlapping swa because I typed too slow, once again.
when written the normal way, two pixels of empty space is added to the right side of each image.

Well, I'm going to explain this whether you want me to or not ;)

<img src="blank.png"><img src="blank.png"><img src="blank.png">
<img src="blank.png"><img src="blank.png"><img src="blank.png">


In html, all whitespace is equal unless you've done something special like <pre> mode. A space = a tab = a line break. Multiple whitespaces collapse to one-- but it's always one. In the example above, images 1-3 and 4-6 are each a group. Between images 3 and 4 is a blank space, exactly as if you'd typed

<img src="blank.png"> <img src="blank.png">

In another thread regarding this same issue it was your advice that I set my FONT SIZE to something that definitely renders smaller than my images because <snip>

I don't think that was me, though I won't argue with the premise. In fact only yesterday (really) I read on another site [quirksmode.org] that sizes of table elements "have always been more like a polite advice than a strict rule". I like this wording. The topic was {table-layout: fixed;} which is the only way to override this behavior. You can constrain the size of a div, a list or a paragraph, but in tables, a "width" or "height" tends to be interpreted only as min-width or min-height.

Do this: In your CSS set

table {border: 1px dashed red;}
td {border: 1px dashed blue;}
table div {border: 1px dashed black;}
table img {border: 1px dashed green;}

This will look horrible but it's intended to. The idea is to show exactly where the whitespace is coming from by drawing lines around all elements. It will also skew your layout a tiny bit because each border adds 1px; this doesn't matter for present purposes.

swa66




msg:4615062
 10:37 am on Oct 7, 2013 (gmt 0)

Instead of setting the border, try setting an outline: they don't mess up your layout and still show where what element is. Or even better use some developer tools to highlight the margins, padding and borders your elements have.

icon_kid




msg:4615792
 4:30 am on Oct 10, 2013 (gmt 0)

I appreciate all the responses I've gotten on this issue including this one that made me laugh:

I honestly don't get why you continue to not want to listen, and refuse to take a step back from the stuff that doesn't work and into a new world.

...and I laugh because I'm actually listening very carefully.

Here is a code that works:
(by the way, I'm interested only in code that works -- why would I be interested in code that doesn't work?)

<div class="row"><nobr>
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
<img src="asterisk.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
<img src="pound.png">
</nobr>
</div>

<div class="row"><nobr>
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
<img src="angstrom.png">
</nobr>
</div>

The problem is that it does not work when placed in a table; by "working," I meaning that there are no spaces between rows outside a table but spaces appear when in a table. It's a simple problem for which I seek a simple solution. So far, the simplist one (and the one I'll try first, of course) is lucy24's which is to merely remove the spaces between IMG tags -- which also means puting the images on a single line.

I'm a graphic artist not a programmer. I've learned only enough Web site programming to create my desktop icon Web site which has been online for more than ten years. This project is not for my Web site and is a unique type of document (unique, at least as creating it in ordinary HTML). It will be used by a single person and I'm sure I'll never be creating anything like it again.

It all boils down to one simple fact: an image is by default an inline element, just like a word of text it sits on a line, allowing space between words (your horizontal gaps) and allowing space for descenders on that line of text (your vertical gaps).

Yes, images are inline elements (like text) but they are different than text in that empty space is not inherently included in them. Take the code of fifteen images above. When rendered on a page all the images touch each other -- the edges all meet top to bottom and side to side and top to bottom-- as if all fifteen were a single contiguous image -- so where are all the line breaks and spaces you say they must have?

Yes, letter characters are inline but they are different than images in that they have some empty spaces built into the font (there is a printing industry term for the 'spacing of characters' but I forget it -- adjustable spacing done by typesetters). Characters must have some empty space around them to be individually recognizable -- the browser is merely puting them all directly side by side and top to bottom as you type them, but you see them as having spaces between them because of the font spaces that are pre-formed. The spaces between words is also determined by the font -- not any coding you do.

Well, I'm going to explain this whether you want me to or not...

That was my way of coaxing someone to come forward -- thank you.

lucy24




msg:4615814
 7:56 am on Oct 10, 2013 (gmt 0)

The spaces between words is also determined by the font -- not any coding you do.

Unless you've said
{text-align: justify;}
in which case I wash my hands of you ;)

You can also code explicitly for either {letter-spacing} or {word-spacing} in CSS. Both can be negative.

Are you saying that if you go
<img src="blahblah">
<img src="blahblah">
<img src="blahblah">
on separate lines in body text, there's no space between images, but if you do the same in tables there is space?

This may, come to think of it, depend on the browser. The infamous "conforming user agent"* is allowed to ignore whitespace before any closing markup such as </i> or </p>. Since an <img> is self-closing, it's possible that some browsers choose to omit adjacent whitespace, while others keep it.

:: detour here to experiment ::

:: does anyone have the remotest idea why Opera takes a week and a half to load up? ::

Hm, now this is interesting. All browsers add a bit of space after (to the right of) an image if there's a line break in the HTML between it and the following one. But only between adjoining images; not after the last in a series, even if there's another line break. This may be where the closing-tag aspect kicks in, since the line break is followed by </p> or </td>. No difference between <p> and <td>.

Browsers other than Opera and, cough-cough, MSIE 5 ALSO add a bit of space below the series of spaced images, even though I don't have a line break in this position. So we're looking at differing interpretations of "space after an image". This is browser-dependent.

Is there some deep hidden psychological reason why you insist on using <nobr> even though it's not only deprecated but utterly unnecessary? I'd really like to see any and all CSS that pertains to your table.


* Euphemism for "all browsers except MSIE <= current-version".

icon_kid




msg:4616344
 10:22 pm on Oct 12, 2013 (gmt 0)

Don't wash up yet becaused we're not finished.

Some of the above reply is confusing to me so what I have to do now is PM a few WebmasterWorld members with real samples to see what anyone can make of them.

I tried the 'no-breaks-between-<IMG>s' code form but that ran into a problem from the start, in that the rows of images in my document have tags interspersed among them other than <IMG>, and any tag placed on a line other than another image tag gives the same effect as having a break (a space) between rows; for example:

Two tags on two consectutive lines are said to cause a vertical space betweem them:

<img>
<img>


Two tags on the same line but with a space between them is said to cause the same thing:

<img> <img>

and that placing them end-to-end like this:

<img><img> ... eliminates the space.

However, any tags that are placed between them, even if everything is on the same line, such as this:

<img><X><img>,"X" being any tag at all -- has the same effect as putting them on separate lines or leaving an empty space between them.

The next suggestion was to simply dump the table -- and place the data that was in the table directly into the <DIV> -- that didn't change anything either.

THE SAMPLE DOCUMENTS

In the first URL (BK-Map-01-TEST.html) you'll see a page with a street map background with what looks like a grid pattern of lines over it. Each square that the lines form is actually an individual image though repeated left to right and row upon row. What makes them look like a grid is because only the edges of the image are visable as a 1-pixel line with the rest of it being transparent. Actually, this little image is repeated around thirty-five hundred times. This form of a "blank" image is being used just for test documents so I can verify the pattern they create. The final one will use a completely invisable image whereby some will be replaced with icon images. The page also has one table across the top of it (irrellevant).

The second URL (lucy-2.html) shows two scrollable DIVs side by side. They both contain tables. The table in the right-side DIV contains more DIVs. The problem is that in the first document all the images are ajacent but in the second one there is a 5-pixel space between rows. It all boils down to one simple proposition:

Since the images are ajacent in the first document, there must be a simple way to make the images in the second document behave the same way. Another way of puting it:

Why are there no spaces between rows in the first document whereas spaces do appear in the second document. This question is very staightforward and is supplimented by two real documents for you to examine. There must be a simple fix for this -- not a convoluted one. C'mon, let's smoke this one away.

swa66




msg:4616352
 11:02 pm on Oct 12, 2013 (gmt 0)

You can't just pick what you want and then expect it all to work. E.g. you use a html5 doctype, but use prehistoric html inside (nobr, font, long obsolete attributes, tables abused for layout, ...)
Chose what level you code against and STICK to that.

First of all validate your code. As long as you're not there, browsers are going to "help", and it'll backfire - big time.

If you want to see what browsers make of your contraptions: use something like the developer tools in FF or inspect element in chrome: they will SHOW you what element is where.
(in case of the code you call lucy-2: it's the <nobr> that causes the vertical gaps.

But it's all irrelevant if this isn't your goal, and how different browsers deal with crappy code is even more unpredictable than usual.

So, what's the ultimate goal ?
Putting icons on a map ?
You don't need a grid for that. You can position the icons anywhere (on or off of a grid). And you certainly don't need thousands of empty cells for that.

Positioning things is much easier, simpler, faster, ... than what you're trying to do now.

So:
- start with what you want as an end goal.
- VALID code: use a validator such as [validator.nu...] or [validator.w3.org...]

lucy24




msg:4616358
 11:56 pm on Oct 12, 2013 (gmt 0)

The first thing that jumped up and hit me in the face was: there is no CSS in the second file. Not internal, not external. You must put your desired defaults into a stylesheet. In particular, there's no point in saying <div class = "row"> if you've never said what the .row class will do.

Aside: Safari's Web Inspector inexplicably claims there is a line
<style type = "text/css"></style>
in the <head>, although this line is invisible to the naked eye ;) In fact I had to re-check the page to make sure you hadn't uploaded a new version between the time I clicked Show Source and the time I turned on the Inspector. Maybe it's their way of saying there ain't none, so stop looking?

Tables are not the only way to ensure vertical and horizontal placement. Look, for example, at the occasional posts involving CSS "sprites"*. In fact your most recent document doesn't really seem to use a table at all, since the structure is simply

<table>
<tr>
<td>
blahblah
</td>
</tr>
</table>

One row, one cell is almost never a table.

Incidentally, you don't need the <tbody> element unless you've got more than one of it (counting <thead> and <tfoot> as versions of "it"). It's a slightly wonky element anyway.

Assignment: Take all the styles that are currently in the HTML, whether in <style = "blahblah"> statements or in the raw HTML as <table cellpadding = "blahblah">. Shift all those styles to an internal stylesheet. Anything that's always the same goes under
table {blahblah}
td {blahblah}
etc. Things that vary get class names
table.map {blahblah}

Finally: Anything using {display: inline-block} falls apart if the window isn't wide enough to hold the two elements. (This applies among other things to almost everything in iOS, which claims to be 980px.) If the two parts have to remain side by side, you'll need a final containing div with its own "overflow" settings.

:: detour to check something in CSS spec ::

Thought so. CSS3
http://www.w3.org/TR/css3-box/#overflow1
allows separate settings for overflow-x and overflow-y -- which is crucial to your overall scheme. (Independent of what you call the elements.) CSS2 was just "overflow".

:: further detour to That Other Forum, since caniuse dot com doesn't have a listing ::

Plausible source [reference.sitepoint.com] says
The CSS3 overflow-x and overflow-y properties are partially supported in Internet Explorer for windows versions 5 and 6 and fully supported in Internet Explorer versions 7 & 8. Safari 3+, Chrome 2+, Firefox 2+ and Opera 9.5+ all support these properties.

That's OK then. MSIE => 7 should cover all reasonable requests-- and I don't believe anyone uses Opera 9.5. Even robots prefer 9.8.


* No, I have no idea why they're called sprites. But when I looked them up, a year or two back, I was astounded to learn that it's something I already know how to do, although I've never applied the concept to CSS. It's the same thing you do in games when a single image file holds a collection of related pictures.

Fotiman




msg:4616366
 12:48 am on Oct 13, 2013 (gmt 0)

The problem that I see with this is the use of the nobr element. It's non-standard, and behaves like an inline element. As others have already pointed out...

DON'T USE THE NOBR ELEMENT!

Seriously, take this advice! Remove all of those <nobr></nobr> tags, then add the following CSS which will achieve the same thing as the nobr:

.row {
white-space: nowrap;
}


You might also want to set the line-height to 0.


.row {
white-space: nowrap;
line-height: 0;
}

icon_kid




msg:4616492
 11:55 pm on Oct 13, 2013 (gmt 0)

Putting icons on a map ?
You don't need a grid for that. You can position the icons anywhere...

Now I really feel like an idiot -- this is all I wanted to do from the beginning -- put icons on a map -- and I didn't know I could do this without resorting to thousands of place holders just to position not more than a hundred icons. What would an image tag look look like if I wanted an imge to be placed at say 218 pixels from the left of a table window and 120 pixels from the top of it? Wouldn't it look something like:

<img src="red_dot.png" pos="218,120">

...but exactly how would it be written because pos="218,120" is just something I made up.

Also, I was wondering how a browser reacts when you inadvertantly position two images to occupy the exact same place or partially overlap. Since images are INLINE they can not overlap. I don't have a need for any to overlap -- I was just wondering what would alert me to it if I happen to mistakenly do this. My guess is that if they overlap by any amount the image that is referenced further in the code (after the first one) just won't be rendered at all.

lucy24




msg:4616501
 2:07 am on Oct 14, 2013 (gmt 0)

Since images are INLINE they can not overlap.

Sure they can, if they have different z-values or if they're set as backgrounds to different elements, such as <body> for one and <div> for another.

Incidentally, I just remembered there's yet another extremely low-tech way to get all those locations: the image map. It doesn't even require scripting.

:: ducking to avoid blizzard of expected objections ::

VALID code: use a validator such as [validator.nu...] or [validator.w3.org...]

Every time I skim this line I do a double-take: "Nunavut has its own validator? Who knew!"

swa66




msg:4616527
 9:03 am on Oct 14, 2013 (gmt 0)

I'll show it in small steps and explain why and what I do to build it, so bear with me.

First off we need a basic template to get valid html (now you don;t need to but this is a polyglot html5 template - I serve it as application/xml - which makes for draconian browser side reactions to errors - I like that - you might not.

So ready for taking a big step backward, away from everything you already have ?


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="UTF-8" />
<title>test</title>
</head>
<body>
</body>
</html>


Next I focus on the html. I want a map and some icons. The decision here is if I want the icons to be clickable (then I need them to be an <a> element, or not (then they can be just about anything else). I'll go for a link as I assume that's what you're after eventually.

Also the map: either I make the image of the map a content <img>, or I set the image in css. since an img in html cannot have child elements, for simplicity I'm going for the CSS background for the map on a div. Now it can be done differently, but it's only going to cause more trouble than you need at this point. Moreover I get much finer control in CSS anyway.

So I add the map (let's assume it's called map.png and is 640 by 480px.
I'll assume for now that my icons will be 20px by 20px and that I have 3 types of data I want to show: gas stations, motels and restaurants.


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="UTF-8" />
<title>test</title>
<style>
* {
margin:0;
padding:0;
}
.map {
height: 480px;
width: 640px;
background-image: url('map.png');
}
</style>
</head>
<body>
<div class="map">
<a class="icon gas" href="/gas?1"></a>
<a class="icon gas" href="/gas?2"></a>
<a class="icon lodging" href="/motel?1"></a>
<a class="icon lodging" href="/motel?2"></a>
<a class="icon food" href="/food?1"></a>
<a class="icon food" href="/food?2"></a>
</div>
</body>
</html>


Note that I do not speak of colors it will be rendered, in the html: it's about content, not presentation.

That should display the map and not much else.

Note that I added 2 classes on the icons: one to tell it's an icon, one to tell what type it is. See I hate to chnag emy html later on, an this gives me as much flexibility as I need. I could (and often do) just use the gas/lodging/food classes as well - the "icon" one is the redundant one to be honest.

So now to the gist of things: absolute positioning.

An absolute positioned element is positioned relative to it's closest parent that has gained "positioning".

Let it sink in: an absolute positioning is RELATIVE to a special kind of parent.

To give an element "positioning" (to make it that special kind of parent): you position the element using position: relative, or position: absolute.

So we put that to use:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="UTF-8" />
<title>test</title>
<style>
* {
margin:0;
padding:0;
}
.map {
height: 480px;
width: 640px;
position: relative;
background-image: url('map.png');
}
.icon {
position: absolute;
width: 20px;
height: 20px;
display:block;
background:red;
}
</style>
</head>
<body>
<div class="map">
<a class="icon gas" style="top: 100px; left: 100px" href="/gas?1"></a>
<a class="icon gas" style="top: 120px; left: 200px" href="/gas?2"></a>
<a class="icon lodging" style="top: 140px; left: 300px" href="/motel?1"></a>
<a class="icon lodging" style="top: 160px; left: 400px" href="/motel?2"></a>
<a class="icon food" style="top: 180px; left: 500px" href="/food?1"></a>
<a class="icon food" style="top: 200px; left: 600px" href="/food?2"></a>
</div>
</body>
</html>


So what's there: display: block on the icons is to make them a block elements as they are normally inline and that won't cut it here.
The position: absolute makes it possible to shift them around relative to the map, as the map is given position: relative.
To position them, since I presume you're generating the html from a database or such, I've added the inline style to tell where the are to be put. I'm using top and left, but you could also use bottom and/or right: that's your choice. Take care tough with using both top and bottom: old IE versions hate that, and with the size of the element already set you make impossible to obey instructions - browsers will "help" you and become unpredictable.

So all that's left now is to add different icons:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="UTF-8" />
<title>test</title>
<style>
* {
margin:0;
padding:0;
}
.map {
height: 480px;
width: 640px;
position: relative;
background-image: url('map.png');
}
.icon {
position: absolute;
width: 20px;
height: 20px;
display:block;
}
.gas {
background-image: url('red.png');
}
.lodging {
background-image: url('green.png');
}
.food {
background-image: url('blue.png');
}
</style>
</head>
<body>
<div class="map">
<a class="icon gas" style="top: 100px; left: 100px" href="/gas?1"></a>
<a class="icon gas" style="top: 120px; left: 200px" href="/gas?2"></a>
<a class="icon lodging" style="top: 140px; left: 300px" href="/motel?1"></a>
<a class="icon lodging" style="top: 160px; left: 400px" href="/motel?2"></a>
<a class="icon food" style="top: 180px; left: 500px" href="/food?1"></a>
<a class="icon food" style="top: 200px; left: 600px" href="/food?2"></a>
</div>
</body>
</html>



Overlapping icons: yes they are possible. The one last in the code will come out on top, your logic that generates them will have to deal with that.

Further improvements:
- make the icons CSS sprites
- or make the icons just plain UTF-8 characters if they have the icons you need (I can't type UTF-8 here AFAIK, so I can't show off) But UTF-8 has more bullets, stars, arrows etc than one can need.

To finish it off: take everything between the <style> tags and put it in a separate css file and use it as an external style sheet.

icon_kid




msg:4616747
 4:39 am on Oct 15, 2013 (gmt 0)

Great stuff, swa66 -- amazing versatility in CSS.

Tonight I had to skim through your very comprehensive reply because my time is short right now. I'll study it and try your code samples on the weekend. Much of it just looks like a cleaner way to achieve the design I want. The nature or the 'utility' of the icons is only to mark a spot on the map. Unlike Google Maps, I won't need my 'map markers' to be clickable. Also unlike Google Maps, I don't need to have any of them overlap, so any extra coding having to do with "stacking" them in some order for 'Z' values can be dispensed with.

Bear in mind that not only do I want to position the icons, but they must also be subjected to the "swap code" -- which you could think of as the prime feature of this whole project. The impetus for this project came when I decided to make a Google Map for my dispatcher and then realized that it wouldn't be nearly as handy as it could be for his needs because of one simple limitation -- a dispatcher needs to be able to hide map markers. As a matter of fact, he doesn't want to see ANY markers untill he starts routing out 'way stops.' In Google Maps you can NOT make a marker disappear except by deleting it (and its 'way stop') completely. Someone in this forum has said that a marker "hide" feature is available in some advanced version of Google Maps but I've already looked into that and have found no evidence that such a feature is present in it. So when I see that something I want doesn't yet exist, but I think I can make it myself, then I'll give it a try -- a Google-looking map with map markers that can individually appear and dissapear using checkboxes. The dissapearing act is accomplished by swapping an opaque image with a fully transparent one. A theorectically simpler method previously attempted was a 'hide' script (to display a single image or not to display it) which was tried, failed and abandoned. So, as long as I can position icons and also swap them with another image then this new CSS strategy will work out for me. The issue of "sprites" is interesting. I'll have to go back and look at what the difference is between a sprite (as used in a Web page) and say a normal PNG image. I know about sprites as a CGI animator, where a sprite is usually just a small, low-res, low-depth 2D image which, because of its small file size, can be processed more swiftly for rendering in a 3D enviornment where action is taking place -- can't imagine why something like a sprite would be used in a Web page, which is usually a static, 2D world.

lucy24




msg:4616763
 7:32 am on Oct 15, 2013 (gmt 0)

I'll have to go back and look at what the difference is between a sprite (as used in a Web page) and say a normal PNG image. I know about sprites as a CGI animator, where a sprite is usually just a small, low-res, low-depth 2D image which, because of its small file size, can be processed more swiftly for rendering in a 3D enviornment where action is taking place -- can't imagine why something like a sprite would be used in a Web page, which is usually a static, 2D world.

Well, I did say I have no idea why they're called sprites ;) It has nothing to do with file format, just how they're used in the html.

Short version: Shovel all your little bitty images into a single graphics file. Then, instead of displaying them via <img src> tags, make each image into the background for a named class. In each different class, the background position is offset by some number (horizontal and/or vertical, depending purely on what your graphics file looks like).

Result: each class shows a different picture, but the user's browser only has to make one request. You'll see it most often with small rectangular images that come in sets, such as a series of social-media icons. Or, in your case, all those different icons for whatever it is you want to show on your map.

This is all CSS2, no cutting-edge CSS3 stuff involved. Well, presumably it doesn't work in MSIE6, but that's not anything we didn't already know.

icon_kid




msg:4618274
 3:26 am on Oct 22, 2013 (gmt 0)

Had a bad weekend and didn't have the extended time I would need to test and document the suggestions offered. Instead, I made an animation that simulates exactly how my finished project would look and function -- because I'm an animator by trade, and beause it was fun to do (wish making it work like that in a Web page was as much fun, though). If a picture is worth a thousand words, then an animation is worth what -- 2000? I've sent a PM to certain members with the link to the simulation video for their reference.

It's obvious what's happening in the animation, but a description should be provided out of general principle:

* There's a column on the left with the names of doctors offices and their locations.
-- each name has a check box and a unique icon next to it.

* There's a much wider column on the right which has a "street map" background on it, and both columns are scrollable.

* When the check box for a particular doctor is clicked, another icon (which is identical to the one next to that doctor's name) appears at his geographic location on the map. If you uncheck his box, then his icon disappears from the map.

* Even though the icon next to a doctor's name and the one that appears on the map are identical, they are two separate files and don't have anything else to do with each other except for the user to associate them visually. The icon that appears on the map, however, is involved in an image swap. When the page loads all images are set to load their 'invisable' versions first -- that's why you don't see any icons when the page loads -- they are there -- you're just looking at invisable pictures. When you click a check box you're swapping an invisable image for one you can see.

I already have the code that makes most of this work. The stumbling block is unwanted spaces between rows of images. Perhaps eliminating the NOBR tags (as Fotiman has suggested) may solve that problem -- even though using thousands of place holders for positioning images is awkward, cumbersome and claimed to be dispensable by using CSS "position" attributes for only the few images that need to be seen (or swapped).

I'm not going backwards from here. I have the swap script and the DIV/TABlE layout -- which will stay as aspects of the final document. Now I have two ways of proceeding:
Either I eliminate unwanted spaces between rows of images (even though that version of my code involves thousands of "place hold" images as well),
or,
I dispense with place holders altogether -- by precisely positioning just the icons I need to have on my map while also having the CSS script for positioning being integrated with/compatable with my "DIV, TABLE layout" and my image swap script.

Something as simple as what the animation shows MUST involve just as simple a programming scheme for constructing it as a functioning Web document.

swa66




msg:4618304
 8:10 am on Oct 22, 2013 (gmt 0)

You cannot mix proper positioning inside tables. Tables is kind of black magic, and browsers according to the standards don;t have to provide for proper positioning inside them. Firefox e.g. doesn't.

Fotiman




msg:4618368
 3:06 pm on Oct 22, 2013 (gmt 0)

Having seen the animation, I now have a much better idea of what you're doing. The entire table can (and should be) eliminated for several reasons:

1. There is a much better (and easier) way to do this, by positioning the images at specific locations on the map.

2. Tables can be unreliable with regards to proper positioning.

3. The table markup is a LOT bigger than a non-table solution. The non-table solution will be much, much smaller, and may load noticeably faster.

:: cracks knuckles ::

Ok, lets start from scratch. Don't worry, this actually won't take very long at all. :)

Fotiman




msg:4618377
 4:35 pm on Oct 22, 2013 (gmt 0)

Ok, here it is, from scratch. I've eliminated your tables and reduced all of the code (including styles and scripts) to 164 lines (with detailed comments to explain everything). Note, I decided to use jQuery for this because it saved a lot of time with the DOM manipulation.

I've eliminated all of the image swap stuff, and instead it injects a new image onto the map at the specified location. All you need to do is populate the clientList section using the template format described below. You'll need to figure out the top/left position for each client image. Also note, my example re-uses the image src that's shown in the clientList so that the image is exactly the same image that gets placed on the map. Why have 2 images that look the same? It's more efficient this way and the browser will already have the image loaded.

Questions?


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Brooklyn Map</title>
<style type="text/css">
html {
scrollbar-3dlight-color:#C6C6C6;
scrollbar-arrow-color:#FFFFFF;
scrollbar-face-color:#5A5A5A;
scrollbar-track-color:#1F1F1F;
scrollbar-highlight-color:#808080;
scrollbar-shadow-color:#484848;
scrollbar-darkshadow-Color:202020;
}

/* Moved all presentational attributes out of body element. */
body {
color: #000;
font-family: Arial, Helvetique, sans-serif;
font-size: x-small;
margin: 0;
padding: 0;
}

/* This container has the map background. It has been sized to the
* dimensions of the background image. It has position relative so
* absolutely positioned images that get placed on the map are relative
* to this container. */
.mapContent {
background: #484848 url('BROOKLYN_map.png');
width: 1427px;
height: 1415px;
overflow: auto;
position: relative;
}

/* This container has the client list. It is positioned within the map
* container. */
.clientList {
background-color: #b5c7e0;
border: 2px solid #93a6bc;
float: left;
margin: 1em;
width: 200px;
}

/* This is the list of clients. List markers have been removed. */
.clientList ul {
list-style: none;
list-style-position: inside;
margin: 0;
padding: 0;
}

/* This is the list item which contains client info. */
.clientList li {
padding: .5em;
}

/* Moved all presentational attributes out of body element. */
a:link {
color: #8f8ffc;
}
a:visited {
color: #b67af6;
}
a:active {
color: #fff;
}

img {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div class="mapContent">
<div class="clientList">
<ul>
<!--
Use this as a template. Each list item must be in this format:
<li>
<input type="checkbox">
<img src="..."
alt="..."
data-position-top="..."
data-position-left="...">
Client Name
<div>Client Address</div>
</li>

The only requirement is that there is a checkbox that is followed
by an img sibling, and that img element needs to have a src
attribute, data-position-top attribute (containing the top
coordinate for the location on the map to show this), and
data-position-left attribute (containing the left coordinate for
the location on the map to show this). The alt attribute is
recommended but not required.
-->
<li>
<input type="checkbox">
<img alt=""
src="client1.png"
data-position-top="500px" data-position-left="500px">
Client 1
<div>Address 1</div>
</li>
<li>
<input type="checkbox">
<img alt=""
src="client2.png"
data-position-top="300px" data-position-left="250px">
Client 2
<div>Address 2</div>
</li>
</ul>
</div><!-- clientList -->
</div><!-- mapContent -->
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
(function () {
/**
* Given an image, create a copy and position it on the map using the
* data-position-top and data-position-left attributes of the image.
* This will insert the new image immediately after the one passed in
* but because it's absolutely positioned will appear on the map.
*/
function showOnMap($img) {
$('<img>', {
src: $img.attr('src'),
alt: $img.attr('alt')
}).css({
'position': 'absolute',
'top': $img.data('position-top'),
'left': $img.data('position-left')
}).insertAfter($img);
}

/**
* Given an image, remove the next sibling image (which was created in
* the showOnMap function) from the DOM.
*/
function hideFromMap($img) {
$img.next('img').remove();
}

/* Attach a click handler to the clientList container that will trigger
* for each checkbox element within the clientList. */
$('.clientList').on('click', 'input[type="checkbox"]', function () {
// this = the checkbox
var $img = $(this).next('img');
if (this.checked) {
showOnMap($img);
}
else {
hideFromMap($img);
}
})
})();
</script>
</body>
</html>

Fotiman




msg:4618389
 4:55 pm on Oct 22, 2013 (gmt 0)

And to help find coordinates on the map, you could add this (but remove it from production code):

$('.mapContent').on('click', function (event) {
console.log("[" + event.offsetX + ", " + event.offsetY + "]");
});

Then for each client you need to add, click on the location on the map where the top-left corner of the image should appear, and use the values that show in the browser console to populate the data-position-left and data-position-top attributes for each image.

icon_kid




msg:4618545
 4:36 am on Oct 23, 2013 (gmt 0)

You cannot mix proper positioning inside tables.
Thank you, swa66, because that is something I needed to know.

fotiman:
Wow! -- this is fantastic. Tables are out -- so be it. I was only half expecting that my simulation would help towards finding the ideal approach to all the scripting. I will test this out and I will surely report back with any issues -- Thanks!
(I got your PM on this too.)

What's interesting to me is that, where I had once tried a so-called "hide" script which would have used only a single image for the "disappearing act" -- which I could not get to function properly, (and to which you perfected a "swap" script for me instead), you are now offering some other kind of image "on/off" effect that is not quite the same as a hide script but which you say will be better suited for my project -- all fine and good and I can barely wait to try it out.

icon_kid




msg:4619550
 4:12 pm on Oct 28, 2013 (gmt 0)

I've tested the code above and it's not suitable for me because the client list column is not within a separate DIV or table, and it scrolls along with the map image. Removing all the NOBR tags and adding this to compensate for them:

<script>
.row {
white-space: nowrap;
line-height: 0;
}
</script>


...did absolutely nothing except to cause the lines to break where I don't want them to.
In 2013 a NOBR tag still causes a line not to break -- and not having it will let lines break if the browser window is resized to a width that is smaller than a given line. What I'll do now is proceed with building this project along with the unwanted spaces between rows of images. It won't be my ideal but it will look virtually the same as if spaces were illiminated. I'm going with Fotiman's 'Swap' code, Lucy24's layout and keep the unwanted spaces since no one is able to figure out why the following code produces no spaces:

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>


...while this one displays a 5-pixel space between the three rows:

<div>
<table>
<tr>
<td>
<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>

<div class="row"><nobr>
<img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"
/><img src="blank.png"/>
</nobr>
</div>
</td>
</tr>
</table>
</div>

...with no one knowing a correct and simple way (a way that actually works) to collapse those spaces.

Thanks for the help from all who have replied. I will now proceed to finish the project -- unwanted spaces intact.

lucy24




msg:4619632
 8:36 pm on Oct 28, 2013 (gmt 0)

<script>
.row {
white-space: nowrap;
line-height: 0;
}
</script>

Was that a posting typo?

swa66




msg:4619671
 10:50 pm on Oct 28, 2013 (gmt 0)

I've tested the code above and it's not suitable for me because the client list column is not within a separate DIV or table, and it scrolls along with the map image


Just not a good enough reason to go back to the "crap" you had before.

Why would you want the html structure be so that you need a "separate DIV" for the client list ?
And what do you mean by "separate DIV", cause it *is* in a div of it's own...

Not scrolling:
Did you try just removing the float on .clientList and replacing it with position:fixed and positioning it where you want it on the screen ?
But take care: what happens if your list is larger than the window ?

icon_kid




msg:4619688
 12:16 am on Oct 29, 2013 (gmt 0)

Was that a posting typo?


Uh, no. I took something a WebmasterWorld member gave me and then I put SCRIPT tags around it.
Did I do something wrong again? -- I wouldn't be surprised if I did.

lucy24




msg:4619702
 1:23 am on Oct 29, 2013 (gmt 0)

Did I do something wrong again?

Well, CSS is CSS and javascript is javascript. Styles have to go in a stylesheet. Unless you're using js to change styles dynamically, but let's not go there.

:: happy because for once I have come across a mistake that I'm 99% confident I have never made ::

This 38 message thread spans 2 pages: 38 ( [1] 2 > >
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.
Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About
© Webmaster World 1996-2014 all rights reserved