I have a rather unusual layout that I'm trying to make a reality. There is a div containing, for sake of argument, that needs to be fixed at 200px from the left and from the top of a wrapper.
I then have a collection of square images that would all be floated and would continue to the edge of the browser window, and wrap around the absolutely positioned div. I know that absolute positioning takes the div out of the doc flow, which means I can't think of a simple solution for this.
Has anyone worked out a way around this kind of problem? Potentially with javascript?
EDIT: Here's the rough layout: link
I'm guessing you want more flexibility, but just in case, if your design is reasonably fixed, you can just use 3 columns (container divs) and sort it all out per column.
If your html is fixed, you could use javascript but I don't know of any ready-made solutions.
I would probably use javascript to do some math and inject dummy images / elements behind the black box at the right positions (keeping the black box absolutely positioned). You could also do that server-side.
Edit: Judging from your image, I would personally use a table. However, it can be achieved with floats:
(image: http://i.stack.imgur.com/KAqxZ.png)
<style>
#cont {
width: 100px;
}
.small {
float:left;
height:25px;
width:25px;
background-color:#00F;
}
.big {
float:left;
height:50px;
width:50px;
background-color:#F00;
}
.long {
float:left;
height:50px;
width:25px;
background-color:#F0F;
}
.long .small {
background-color:#F0F;
}
</style>
<div id="cont">
<div class="small"></div>
<div class="small"></div>
<div class="small"></div>
<div class="small"></div>
<div class="long">
<div class="small"></div>
<div class="small"></div>
</div>
<div class="big"></div>
<div class="small"></div>
<div class="small"></div>
</div>
Original text:
I would do something like this:
<div class="absolute-wrapper">
<div><!-- whatever content you intended for the absolute div... --></div>
<div class="float-left">...</div>
<div class="float-left">...</div>
...
</div>
However, I feel inclined to recommend you search for another solution than an absolutely positioned element. They easily grow unmaintainable.
You could do this with a canvas element, but it has downsides. You will be depending on javascript, as you will need to do all positioning in javascript.
Not to be unhelpful, but I also think you should consider how important this exact design is, simply because I don't think there is any straightforward solution, since HTML as it is today isn't really built for these kinds of layout. The future is promising though, giving us things like multi-column and flexbox...
Using javascript/jQuery, it could be accomplished using the logic of the following pseudo code:
Create a function which preforms these steps....
Step 1: Remove any divs from the dom that have a class named fakeSquare. Something like
$('.fakeSquare').remove();
Step 2: Calculate the number of red divs in one row. Store this number in squaresPreRow. Something like: var squaresPreRow = floor( window width / square width ).
Step 3: After the squaresPreRow + 1 red square div, add two empty divs. Like so...
$("div.redSquare")
.index(squaresPreRow + 1)
.append("<div class="fakeSquare redSquare"></div><div class="fakeSquare redSquare"></div>");
Step 4: Add another two square for the third row...
$("div.redSquare")
.index((squaresPreRow * 2) + 1)
.append("<div class="fakeSquare redSquare"></div><div class="fakeSquare redSquare"></div>");
Step 5: And again...
$("div.redSquare")
.index((squaresPreRow * 3) + 1)
.append("<div class="fakeSquare redSquare"></div><div class="fakeSquare redSquare"></div>");
Finally you want to call this function when the DOM is ready and whenever the window changed.
This may need some tweaking, but hopefully it can get you started.
Related
I have some text inside a <p> that is inside a <div>. I have a css image shape that floats to one side. I want the text in the two upper boxes to wrap to the shape but also align to the bottom of the div. The two lower boxes work fine because I do not need to vertically align the text within them. The problem is, the text can vary in length and so can the amount of lines, so I can not use a fixed height. Therefore absolute positioning will not work, plus the text will ignore my floating css image shape.
I have read dozens of questions and answers and all of them seem to use hacks. There is also one question that seems to ask the same as mine, but I can't find it anymore, besides there was only one answer which was javascript based. I tried using flexboxes with align-items:flex-end; but that doesn't work well with my floating shapes. I also tried using a table and vertical-align:bottom; but my text just breaks to another line and doesn't wrap to the shape.
A workaround I came up with is to use padding-top on the text, but not knowing the height of the text means the text does not always position it to the bottom of the div, especially if the length of text changes.
EDIT: I am totally open to any new ideas. This was just the best approach I could come up with. I even started toying around with the idea of using only one shape for all four boxes. But that seems a bigger challenge.
EDIT: I also updated the URL's so you can now run the code snippet.
EDIT: I have decided to go the Javascript route and am working on a solution. I am open to any ideas.
EDIT: What bothers me the most, is that every single idea I come up with requires an army of Javascript. The solution, in my opinion, should NOT require a nightmare. CSS should be able to solve this, but I can't seem to find a way without Javascript.
div, img, p {
margin:0px;
border:0px;
padding:0px;
}
#wrapper {
display:block;
position:absolute;
left:0px;
top:0px;
width:100%;
height:100%;
}
.box {
display:block;
position:absolute;
width:50%;
height:50%;
}
.box p { line-height:1.5em; padding:10px; }
/* The image shape is 300px x 300px. * /
/* I use 50vh because I want the shape size to always be half of the window height. */
/* This gives the illusion of one larger shape. */
.shape {
position:relative;
shape-margin:2em;
width:50vh;
height:50vh;
}
/* My workaround solution - #top_left p, #top_right p { padding-top:29vh; } */
#top_left { right:50%; top:0%; }
#bottom_left { right:50%; top:50%; }
#top_right { left:50%; top:0%; }
#bottom_right { left:50%; top:50%; }
#top_left p, #bottom_left p { text-align:right; }
#top_right p, #bottom_right p { text-align:left; }
#top_left .shape { float:right; shape-outside:url('https://i.stack.imgur.com/B1Dzu.png'); }
#bottom_left .shape { float:right; shape-outside:url('https://i.stack.imgur.com/Vxmz0.png'); }
#top_right .shape { float:left; shape-outside:url('https://i.stack.imgur.com/UL8uT.png'); }
#bottom_right .shape { float:left; shape-outside:url('https://i.stack.imgur.com/EGBRz.png'); }
<div id="wrapper">
<div id="top_left" class="box">
<img src="https://i.stack.imgur.com/B1Dzu.png" class="shape" />
<p>Here is some text. Here is some text. Here is some text.</p>
</div>
<div id="top_right" class="box">
<img src="https://i.stack.imgur.com/UL8uT.png" class="shape" />
<p>Here is some text. Here is some text. Here is some text.</p>
</div>
<div id="bottom_left" class="box">
<img src="https://i.stack.imgur.com/Vxmz0.png" class="shape" />
<p>Here is some text. Here is some text. Here is some text.</p>
</div>
<div id="bottom_right" class="box">
<img src="https://i.stack.imgur.com/EGBRz.png" class="shape" />
<p>Here is some text. Here is some text. Here is some text.</p>
</div>
</div>
I have created an image to illustrate. The pink borders are just to show the box boundaries.
shape_top_left.png
shape_top_right.png
shape_bottom_left.png
shape_bottom_right.png
The best you will probably achieve is through using the shape-outside property
Check out here for some documentation.
However, be warned as of 2019 this isn't supported in Internet Explorer or Microsoft Edge
A simple enough codepen example would be this
Well here is my Javascript solution. It requires a lengthy script so I will just get to the core of the solution.
The Workaround
With my CSS image shape floating to the right I can still get wrapping text, even though I want my text to align to the bottom. Since no working spec I have seen allows me to vertically align my text to the bottom and get it to wrap to a CSS shape, I need to create the illusion with padding-top. I solved the dilemma of not knowing my text height by running a series of checks through a loop in Javascript. Just check the initial height of the text, then add a single increment of padding-top, then compare with the parent container's height. Repeat this process until the text height reaches or exceeds the parent containers height. The important thing here is that each time you add an increment of padding-top, you change the height of the text. The more padding you add, and the closer the text gets to the CSS shape, the more the text wraps and flows differently. This is why we need to check the height on each increment. Since my text has a font size in EM units, I would have a hard time knowing it's computed height doing guesswork. Add in client zooming and it's a math nightmare! Rather we just check with single increments and no math needed, hooray!
My Javascript
This is just a core example, not the full script, but you should get the idea.
var counter = 0 ;
function checkHeight()
{
var container = document.getElementById("top_left") ;
var text = document.getElementById("top_left_text") ;
var container_height = container.offsetHeight ;
counter++ ;
text.style.paddingTop = counter + "vh" ;
var text_height = text.offsetHeight ;
if ( text_height < container_height ) { checkHeight() ; }
}
Another Future Solution
Using CSS Exclusions.
With CSS Exclusions you can have an element that does not float but, behaves like a floating element, so that content wraps around the element in much the way that floating elements do. Unfortunately, there is almost no support for this technology at the moment. That said, I would strongly encourage anyone interested to join the discussion and get more buzz going for the draft to maybe become a real spec. CSS Exclusions open up some really cool possibilities that, in my opinion, bring HTML out of the stone age in terms of document flow.
In the case of my problem here, I would simply be able to absolutely position my CSS image shape and get my layout without the need of Javascript. My text would be vertically aligned to the bottom because there would be no floats to say otherwise.
For those who want to know more about CSS shapes, read this excellent article.
I am creating a template and I want to know how to Auto Arrange multiple height box in css or javascript.
I already tried to change the CSS and Javascript and I've also searched on Google but I've had no luck yet.
I am giving here image for clear to know what i am looking for i am showing in this image...
please check image before replay what i need
thank you
Have you looked at a library like Masonry?
http://masonry.desandro.com/
To auto-arrange elements with differing heights, there are a bunch of different libraries out there you can use. One such library is Masonry.
Try out the snippet below:
new Masonry(document.getElementById('container'), {
itemSelector: '.item'
});
.item {
width: 25%;
}
.one {
background-color: orange;
height: 100px;
}
.two {
background-color: green;
height: 150px;
}
.three {
background-color: blue;
height: 200px;
}
<div id="container">
<div class="item one"></div>
<div class="item two"></div>
<div class="item one"></div>
<div class="item two"></div>
<div class="item three"></div>
<div class="item three"></div>
<div class="item one"></div>
<div class="item two"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/3.3.0/masonry.pkgd.min.js"></script>
Take a look at existing tools to do this like Shuffle and masonry. (Shuffle actually uses masonry.)
You haven't provided much detail so my answer can't have much either. It looks like you are looking for CSS Columns. Tables with table-layout: fixed; might also be of use. These layouts are called Pinterest Layouts or Mosaic Layouts
I have good news and bad news, followed by more good news.
The good news is that flexbox is exactly the sort of thing you could use out-of-the-box for this. No js required -- You will set up the flow direction to be in column mode, and you will turn on wrapping. I've provided a fiddle:
https://jsfiddle.net/cev0ug3y/
The bad news is that for this to work, you have to know the height ahead of time. This is fine when you have a small fixed set of items to show, or if the scrolling is set up to be horizontal, but it's not so good when you want that Pinterest-like infinite scroll.
The good news is that there are a lot of people before you who've solved this using javascript -- I'd really recommend using one of those. Refreshing the answers, I see Masonry and Shuffle have already been suggested, so I'll throw in one of my favorites (by the guy who wrote Masonry): Isotype - http://isotope.metafizzy.co/layout-modes.html
If you still want to roll your own, the idea is very simple:
Initialize an array of leading edges which record the vertical height of each column of your display. You'll be initializing this to zero.
For each item you need to place, find the minimum leading edge who, with its neighbors, can accommodate your item.
Set the leading edge of all participating columns to the value of the leading edge you chose plus the height of your item.
You will be using position: absolute to do this. If you don't know the height of images ahead of time, you might be stuck waiting for the load to complete before placing each item. If your items are different widths, you may have holes in your display, and there are techniques to minimize this, but it doesn't look like that's what you are doing here. Despite all of these caveats, this should get you started, but I'd still look at third party libraries for inspiration.
Sorry, I know that title isn't very parseable (or even complete). This should do better than words:
Note that x and y are dynamic heights based on the contents of those children, and there is no guarantee that one will be larger than the other.
I don't want to use tables and I don't want to rely on CSS3 (for solutions like calc.) I think this means that one of the two columns must be taken out of the "static" layout, because of the dynamic width requirement. And because of that, I think that means there is no way, outside of Javascript, to size the parent container to the max of its children columns' heights.
I hope someone proves me wrong, because I'd love to do this in CSS. Thank you, wonderful SO community!
Demo
<div id="wrapper">
<div id="sidebar"></div>
<div id="main"></div>
</div>
#wrapper, #main{
overflow: hidden;
}
#sidebar{
float: left;
width: 100px;
}
Is it possible to have two divs wrap as if their one line?
<div class="multiLine">
<div class="topLine"></div>
<div class="bottomLine"><div>
</div>
so if top line was all "A"'s and the bottom line was all "B"'s we would see it wrap like
AAAAAAAAA
BBBBBBBBB
AAAAAAAAA
BBBBBBBBB
I'm trying to accomplish this with JavaScript, jQuery, and css3.
This could actually be done just by using CSS and playing with the div positions and the line heights.
For example:
.multiLine {
position:relative;
width:100px;
eight:100px;
}
.topLine {
position:absolute;
word-break:break-all;
line-height:40px;
top:20px;
}
.bottomLine {
position:absolute;
word-break:break-all;
line-height:40px;
}
This would work although it may not be an optimal solution for what you want. It depends on the context and what you want to achieve with this effect.
EDIT: You can see an example of how it would look like here: http://jsfiddle.net/78f94/
You cannot do it with html/css alone. But with Javascript you can find viewport width, truncate the string and add it as content to new inner divs. This could get very complicated when you resize as width changes!
Here is more info on getting viewport width: Get the browser viewport dimensions with JavaScript
This demo, which goes along with this article, succintly describes what I need to do. However I am not impressed by the use of javascript for something that should be possible in pure CSS.
The articles referenced (which I also found independently when looking for a way in CSS) don't perform the same function as the watchmaker demo - the 456 boxes demo doesn't slide under the other boxes when the screen width gets too small.
I've been playing about with the article code and trying various ideas in CSS, but nothing lays out correctly. Also I would prefer progressive enhancement over graceful degradation.
I realize this is an old question, but I wanted to bubble up the answer you should be using now: flexbox. The original demo from the question is long gone, but the markup was this (courtesy of the Wayback Machine):
<div id="one">I am 150px high</div>
<div id="two">I am 200px high</div>
<div id="three">I am 120px high</div>
<div id="four">I am 300px high</div>
In order to equalize the heights using flexbox, you would need to have a container wrapped around them:
<div class="container container--equal-children">
<!-- those four divs -->
</div>
Setting that to display: flex and setting align-items to "stretch" gives the desired effect:
.container--equal-children {
display: flex;
align-items: stretch;
}
Once that’s in place, you can skip the whole sizing thing and let the children flex to fill 1/4 the space:
.container--equal-children #one,
.container--equal-children #two,
.container--equal-children #three,
.container--equal-children #four {
flex: 0 1 25%;
}
They will all automatically be the same height.
I put together a CodePen that lets you toggle the flexbox rules on and off. It’s worth noting only the toggling functionality requires JS. There are also some "for presentation only" style rules I’ve added (which are noted) to demonstrate the design behavior.
Unfortunately, there really isn't a good way to do it in pure CSS. I assume that you want a dynamic height of containers based on a single parent container. Cross-browser issues make it an absolute nightmare, and the relatively small amount of JavaScript needed to accomplish the effect, IMO, is a better approach than trying to maintain really ugly and nasty CSS rules, having to import other CSS rules to fix things in certain browsers, etc, etc.
There's a reason these "equal heights" scripts even exist, and it's because of how much of a hassle the effect in pure CSS is.
I would stick with the JavaScript solution.
This is something which you'd think would be simple but is actually really tricky.
The "sliding under" aspect isn't really related to maintaining the same size. That's just how floating works. They probably have a rule like:
.box { float: left }
with markup like:
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>
If they gave .container a fixed width, that would prevent the .box's from sliding under each other.
If all you're looking for is to have background colors under various boxes of fixed width, there is an easy way to accomplish this without JS.
You can give .container a background image that has the backgrounds for all the boxes and tiles vertically. With your first example, it would be only a few pixels high with a 200 px section of orange, 200px of blue, 200px of red, and 200px of green.
Since if you "clear" the .container it grows to contain all the boxes, the background boxes would appear to all be the same height.
Anything more complicated such as vertically centering the text in the second example, and you're probably better off going with one of the JS scripts to even out the boxes.