Calling all web gurus: I need your help (CSS)

fisicx

Moderator
Sep 12, 2006
46,962
9
15,519
Aldershot
www.aerin.co.uk
Divs and floats is your answer.

Just float the images and see what happens. If there isn't any room for the RH image it will drop down the the next available line.
 
Upvote 0
D

DotNetWebs

Interesting exercise.

If it was me I would do the whole thing by dynamically creating the markup with inline styles using absolutely positioned and sized divs.

From the dimensions you have given I would model [in code] a 750px x 750px grid divided into 15 x 15 blocks of 50px.

Each of your images can be dived into whole 50px blocks so you could randomly choose the starting images (e.g top left) and calculate the boxes used and therefore the boxes remaining. You could continue to loop selecting randomly or (where forced) fixed sized images until the grid was full.

Regards

Dotty
 
  • Like
Reactions: FireFleur
Upvote 0

fisicx

Moderator
Sep 12, 2006
46,962
9
15,519
Aldershot
www.aerin.co.uk
I am already using floats and divs - see source code.

You've changed the page! I now see the problem and realise that float ain't gonna cut it. Dotties solution seems very elegant.
 
Upvote 0
D

DotNetWebs

I have just read my reply again and just to clarify you obviously would end up with ALL 50px x 50px divs but divs that were MULTIPLES of 50px x 50px. Together they would make up the entire 750px x 750px image area.

It's a bit like coding for a 'Tetris' type game!

Regards

Dotty
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
3 cell table.

The design is tabular in nature, you use a table.

The last cell is a bit annoying, so could break the rule, but as shown each element would just follow after.

For complete generality then position absolute is the way, but it can be awkward around the rest of the page.

So, an iframe might be used as well so you can hold the content and flow the rest around it if you are going to be using absolute positioning.

If the images are 'random' but create a rectangle in the whole, then you could use server side scripting of the CSS or JavaScript on the client side.
 
Last edited:
Upvote 0
D

DotNetWebs

4 cell table.

The design is tabular in nature, you use a table.

Yes you could do it in a table but the OP specifically asked for CSS so I used that.

You would need more than 4 cells though to accommodate all possibilities of [random] image sizes while maintaining the image alignments.

I would still start with a 15 x 15 grid and merge the cells as required.

Regards

Dotty
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
Another way would be to do image combination on the server side.

I would probably do it by DOM and javascript. Throw the images central in the rectangle using server side scripting. Then move them into position using the DOM.

The selection process from the database is going to be the interesting one, and most of the algorithms and functions you need to do the other parts will be already be done there.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
Yes, I noticed he is actual problem later :)

The table with 50 x 50 cells is probably the best one, just use colspan and rowspan for the multiples.

Interesting I started going down the absolute position line after thinking table, but yeah it is a table, avoids the use of an iframe and absolute positioning.

The 50 x 50 can even be changed to accommodate a different lowest common denominator.
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
You could also use a block element that has the overall dimensions fixed, and use its position to calculate an offset and make other elements flow around, if you want to avoid the iframe, but it is complicated and uses some odd features of the DOM both in events and getting the browser positioning of the element.

The table is the best way, it renders in the flow, so they can change text size and it doesn't all break.

Taking the table cell and 50x50 cell dimensions, you will notice I said 4 at the start, then changed it to 3, that was because of the last cell it looked like 4 but of course that can be done by 3. If the penultimate image block instead had a cut in the horizontal to make another block below, then 4 would have been the minimum. If you can get those type of rules in, and produce a table with the minimum number of block elements, it will render faster.

Quite a fascinating problem :) And CSS does involve tables, there are specific table CSS parameters, but really the problem is one of layout, and using the table elements because of their special html attributes and their specific CSS style properties.
 
Last edited:
  • Like
Reactions: MichaelG
Upvote 0

MichaelG

Free Member
Sep 1, 2005
461
16
Berkshire
FireFleur,

If I go the table route as a short-cut to this problem, will this work?

01: Create a table with x rows and x columns - each cell is 50 x 50
02: I get the first image and work out how many cells I need for the width and height of the image by dividing the height and width by 50 - e.g. image w150 x h200 gives 3cols x 4rows of my table.
03: I dynamically create the required cell for the current image.
04: I know the total width of my table, so repeat this until I can fill all the columns - once the total width of first lot of images reaches my maximum table width, I start the process again.
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
Tables aren't inherently bad, there was a time when people went for tableless design using a subset of CSS, just to prove what could be done.

But here, you want the table to avoid the absolute positioning problem, if you use absolute positioning or relative even you end up removing elements from the document flow so you often have to rejig things.

The 50x50 grid idea by Dotty is the start point, the table is the simpler way of doing this (no absolute), and you can say with the 50x50 idea or you can further refine it and allow line breaks in the cells (but that is more challenging to extrapolate).

Well you have a number of stages to the overall problem:

The first is in selecting a number of images that will produce a rectangle of the dimensions you want.

So assume you have 15 x 15 of 50 x 50 cells, so 750 x 750.

The first image can be a maximum of 750 x 750 let's say it is 500 x 700, the next image can be 250 x 750 and let's say it is 250 x 100.

That is the top row done. But you now have a jagged line below to fill, and it becomes harder to find a filling piece towards the end.

So, you might want a few 50s in there, but that will tend to make the last few 50s :)

Once you have the pieces that make up a rectangle, then filling the grid on 50 x 50 is a simple division by 50 of the dimensions and applying that to colspan and rowspans.

But for extra marks you can also reduce the number of cells to a minimum so if you find for example all are even colspans of 2 or more, then you could divide by 2, and line breaks could be used to reduce the number of rows, though this is more advanced and therefore you could introduce an error quite easily.

It is the first bit that is hardest, and some of it could help in the last bit if you want to go the extra mile.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
I would be tempted to pre generate the patterns, and then allow a random selection from the patterns, and a random selection of the images filling the pattern.

That way you can see if something is going to be a problem before hand, and only deliver up those that work.

So you may get a pattern that works as a pattern but you don't have enough of a particular shape image to make it work, you can just reject that ahead of time.

You can also reduce the number of patterns that end in a 50 x 50 or rotate the patterns to get more variation in how they end. A rotation would mean you would have to check for fitting images (90 degrees - 180 degrees you wouldn't [ a mirror ] ).
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
If by CSS you mean absolute positioning then it is harder to do that without using table elements.

It is an odd thing that CSS and tables have been placed at logger heads, they are not the same thing as we all know, and CSS can be used with tables.

There are CSS properties of tables:

border-collapse
table-layout

etc

and CSS display values:

table
table-cell

So using CSS doesn't preclude tables, if you don't want to use table, then the term is tableless.

http://www.w3.org/2002/03/csslayout-howto

And that is an interesting page, the URL does say CSS layout, but notice the titles are Tableless, so there is a bit of a mission going on to sort out the misunderstanding.

The problem with tables is the 4 box minimum, so over use in embedding can mean 12 embeds before content is hit. But the actual rendering properties of tables are useful for some layouts, there is a base line that expands to fit the tallest cell and that is something you cannot do without DOM manipulation if you go tableless, you have to specify fixed heights or make do with a variable gap at the bottom.

If your design is a bordered grid, then the layout is normally a table, there are other things like center right aligns you cannot do without using a table :

Code:
|   Variable Heading     |
|               info     |
It is the over use and the reach for the table without looking for simpler things was the problem. And CSS is getting more features in the future which will mean that one day as long as the browser folk do implement them correctly, tables can finally just be used for tabular data.
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
It is not so much the ul or div debate, they are just blocks, it is the rowspan and colspan attributes of tds versus coordinate positioning.

You can change display values of items, though it gets a little daft when you embed divs with table display values, that is a table and the problems of it.

But the attributes don't carry over for different display types.

And in this instance you cannot get the blocks to fall into what we would think of as the logical way without using positioning or the col/rowspans.

You end up with this

Code:
XXOXXX
XXOYYY
   OZZZ
that is with float (the Z is wrong).

without float:
Code:
XXOXXX
XXO
  O
YYYZZZ
(breaks at Y there)

If you cut all the images up into many 50 x 50 chunks that would work without tables or CSS getting involved in the layout.
 
Last edited:
Upvote 0
D

DotNetWebs

If by CSS you mean absolute positioning then it is harder to do that without using table elements.

It is an odd thing that CSS and tables have been placed at logger heads, they are not the same thing as we all know, and CSS can be used with tables...

By "CSS" I mean using formatted DIVS for layout instead of tables. As you say this often causes 'heated' debates. I wasn't trying to argue the case for either but simply answered the original question and then agreed that it would be equally achievable using tables (or even a mixture of the two).

For the 'CSS' option I would use absolute positioning and disagree that it "would harder to do that without using table elements" (principally because you would know the images sizes in advance so would not have to cope with expanding elements etc.)

On reason that a 'CSS' might be more appropriate for this idea is that often a table won't render in a browser until all the elements are loaded. If you are using lots of images this might appear as a significant delay in page loading on slower connections. With the 'CSS' option the images would load sequentially allowing the images to render as the page loads.

Regards

Dotty
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
Yeah the problem with absolute positioning, is the rest of the page :)

So if you have a header and some text above, and someone enlarges the font size, then it will spill under or over the image grid which has been positioned absolute.

If you use relative then you have to do a lot of crazy calculations, and again it is prone to error, there will be odd cases where the relative position is not where you would expect.

So an iframe could be used to get around that, but that will be loaded after generally.

Rendering the most embedded last, I don't think that is true across all browsers.

If you think about it you want to render down the page not at embed levels, otherwise you will render something then have to move it, as the next level moves it down.

It is more efficient to render nodes and their children first for display, so a depth first render. It is an interesting point there could be browsers that do a breadth first render though I would be surprised, what most pages want is the code order to be rendered first on the page.

I might do a test for that :)

Ok, I have a page with an image embedded in a table (level 4) then an image that doesn't end (level 1).

The embedded image shows without waiting for the other image to arrive.

Interestingly when I add another image after the image that never ends, which is done by /dev/random as the src, the third image doesn't display.

So firefox is using a depth first render.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
I think I DoS'd the browser doing that :)

IE could be doing a breadth first render that is possible.

Dare I try it with Opera :)

Cutting the images would be an interesting one, but it would create more file requests. If done with a low res image as well it could be quite arty.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
It looks a little more complicated on the render front than just a depth or breadth first search.

Creating an infinite loop of javascript renders, still has depth first.

But when the first occurring element is written using a document.write nothing displays.

So, it is probably depth first and related things grouped, but it is actually quite hard to find a definitive test that can be done to show the render order.

Next stop source code :)
 
Upvote 0
D

DotNetWebs

Why can't you use a simple inline list?
Format the list via css(separate css file, no inline css) with auto height so that various height images can still be displayed.

If I understand correctly the OP is trying to recreate the pattern below using RANDOM images WITHOUT knowing in advance their exact dimensions. i.e the pattern will be different each time.

I would be very impressed to see am external CSS file that could cope with this.

Regards

Dotty

ps Michael, hope you don't mind be embedding your image

csstest.jpg
 
  • Like
Reactions: MichaelG
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
The position absolute into the relative container does work in the major browsers. This approach did have some problems though.

And whilst a containing div is being added, and the coords need to be given, it probably has the edge on a number of table rows and cells, and definitely over an iframe.

And the containment allows for the object to be placed elsewhere easily without having to recompute.

Good call Dotty :)
 
  • Like
Reactions: DotNetWebs
Upvote 0
D

DotNetWebs

Personally, i'd use tables - nice and easy

I wouldn't say it was THAT easy. Whatever method you choose you, to get RANDOM images of RANDOM sizes, you are going to require a fair amount of [ideally] server-side coding.

When I said it shouldn't be "too much of a problem", what I meant was that it is a LOGICAL problem so it wouldn't be to hard to create an algorithm to create the markup layout dynamically.

Regards

Dotty
 
Upvote 0

MichaelG

Free Member
Sep 1, 2005
461
16
Berkshire
If I understand correctly the OP is trying to recreate the pattern below using RANDOM images WITHOUT knowing in advance their exact dimensions. i.e the pattern will be different each time.

This is exactly what the application will do. Thanks Dotty. I have tried the table/cell idea and I still get this to work. I might need to push this problem out to the wider tech community - if a solution is found, I will make the code open-source.

ps Michael, hope you don't mind be embedding your image

No problems.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
Are you missing a 'cannot'?

If you are, the problem is in two stages.

The selection of the pattern that has to fit the ( a? ) rectangle, and the images have to be available for the pattern.

Then the layout, and there you can use a table or absolute positioning inside a containing div that has a position value of relative.

The first problem, you build a set of heuristics and prepare the patterns ahead of time, each pattern you validate for being possible. And the randomness you place in the selection of pattern and image.

One validation which is part of the way to a valid pattern, would be, is the area of the images equal to the area of the rectangle, if it is not then the pattern is not valid.

The layout problem is solved in a few ways, all above. It is the actual structure of the pattern which is the heavy lifting here.

And it can be solved in a number of ways, but it is spatial geometry with a flavour of AI in it, so pre calculating the patterns is wise. Otherwise you will have to validate on the fly.

So come up with a data structure that can describe your pattern. It could be a list, going from left to right:

[ { { cols, rows, src }, ... }, { { cols, rows, src } } ... ]

or you could map each grid point itself, or perhaps both.

The one above, separates on images and rows.

The run rules over them to see if they are valid.
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
If you don't need it to be generic, for all rectangles and all set of image dimensions.

Then you can prepare the patterns by hand yourself, that takes out a huge chunk of work, just make the patterns that work and select form those.

Or you can brute force combinations, just take the image dimensions you have and fire them at the pattern in permutations, those that fit you keep the others you discard.

There are many ways to solve the problem, if you are on a deadline, then you probably do it by hand, unless they want to use this in the most general sense.
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
If the layout is still perplexing you then it looks like this:

<table
cellspacing = "0">
<tbody>
<tr>
<td
colspan = "2"
rowspan = "2"
><img
src = "img1.jpg"
width = "100"
height = "100"
></td>
....

</tr>
</tbody>
</table>

or

<div
style = "position: relative"
><img
src = "img1.jpg"
style = "
position : absolute;
top : 0px;
left : 0px;
"
width = "100"
height = "100"
/>

...

</div>

So in the table you change the rowspan and colspans to match the pattern.

In the div you change the top and the left values to match the pattern.

There is not too much in the amount of code between the two really, there is a little extra in the table but it is marginal.
 
Upvote 0
D

DotNetWebs

OK proof of concept time!

I had a couple of hours free yesterday afternoon so I thought I would try something.

I have used all the sizes of the 'womans face' image on your test page to randomly paint on a 750 x 750 px canvas

It still only works for the few rows (and only 100% for the first row) but with a bit more coding it will be there.

I have OO modeled in C# the grid, images and shapes etc. The code will randomly choose images to occupy unused cells selecting only the images sizes that will fit.

When the grid is full (or currently when it hits certain limits) the data is used to create absolutely positioned DIVS.

Like I say its VERY rough but the concept is there.

Ignore all the data on the screen it is just for debugging although Firefleur you may like to enlarge the text size to prove it doesn't affect the absolutely positioned DIV :)

http://dotnetwebs.com/test/imagegrid/

Scroll down to the image and continually refresh the page (you may get the occasional .net error but just refresh again)

Hovering over the images in IE will show the sizes used.

Regards

Dotty
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
In the links2 browser ... :)

You are keeping a tally of the used grids, I think that is the problem to be solved, the actual patterns themselves and if there are images to fill those patterns.

Pre calculation is going to be easier, then you don't have to keep the tally either, just copy the pattern to coords or rowspans and colspans.

It is an interesting problem, it is one where it makes the coder in you beam a little to solve :)

the layout I think is this:

Code:
# assume a [ [ (cols, rows) ] ... pre gen valid pattern

for row in pattern:
    print "<tr>"

    for cell in row:
        img_src = random_image( cell[0], cell[1] )

        colspan = cell[0] # left = cell[0]
        rowspan = cell[1] # top = cell[1]

        if colspan == 0 or rowspan == 0:
              continue

        print_cell( img_src, colspan, rowspan )

    print "</tr>"

def print_cell( img_src, colspan, rowspan ):
    print """<td
colspan = "%d"
rowspan = "%d"
><img
src = "%s"
></td>
""" % ( colspan, rowspan, img_src )
The trs with no content could be problematic, but they should work.

Because of that though I would be more tempted with coords, though the table would work without CSS, but only really Dillo and links2 would benefit from that.
 
Last edited:
Upvote 0
D

DotNetWebs

I am not using HTML tables. The 'cells' in the debug code are just part of the mathematical model.

This with definately work. The model currently only checks for horizontally free 'cells' when I get the time I will add the vertical checking etc.

There are no precalculated patterns. It will just fill the grid with the images available.

Regards

Dotty
 
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
I know you are not using tables :), I put in the comments the same place for the coords and it is just a matter of removing the table noise and adding the style noise.

The layout I think we have proven works both ways coords or table spans.

It is the pattern generation that has the constraint of available images and filling the defined rectangle, that's the hard one to crack.

If it is done in real time, it will eventually work then some oddity will make it break, pregen patterns that are validated and selected from is going to be simpler.

It is something like this:

given a rectangle of dimensions X Y and a set of images with varying dimensions, what are the valid image layout patterns that can fit that rectangle with no gaps and each image used only once(?) ?
 
Last edited:
Upvote 0

FireFleur

Free Member
Oct 29, 2008
1,880
440
If you find one pattern, then you can immediately generate 2 more patterns (the horizontal and the vertical flip) hmm maybe get 3 more out of that.

You can also test for two 90 degree rotations.

And I think if they work then you can flip them and get 2 extra patterns.

Some patterns will work for many images so the actual number of images of equal dimensions forms another subset of permutations, but that can be modelled in real time.

You may also be able to scramble the fitting patterns to see if you can make another fit, and that is the area being valid, moving one of the corner pieces to a non corner location would be enough to get a new pattern attempt, and there is probably something in that for just moving bits around, so four 2 x 2s are one 4 x 4, and so could replace the 4 x 4.

So, one approach could be to reduce the pattern layouts to only those which combined have the same area as the rectangle, and then start a brute force from there.

On a match apply some heuristics and get a couple of other patterns, and keep your fingers crossed for 3 or 6 more, then scramble that pattern, and then back to the brute force.
 
Last edited:
Upvote 0
D

DotNetWebs

Upvote 0

Latest Articles