Andreas Louv
Andreas Louv

Reputation: 47117

Linking multiple elements together so they are sharing the same content

Is it posible to have two elements sharing the same content:

----------
| Line 1 |
| Line 2 |
| Line 3 |
----------
    [SOME OTHETR STUFF HERE]
----------
| Line 4 |
| Line 5 |
| Line 6 |
----------

Or a more complex example, using css3 columns

------------------- --------- --------------------------------
| Line 1 | Line 4 |   OTHER   |    Line 7    |    Line 10    |
| Line 2 | Line 5 |   STUFF   |    Line 8    |    Line 11    |
| Line 3 | Line 6 |   HERE    |    Line 9    |    Line 12    |
------------------- --------- --------------------------------

Hope this makes sense?

Also the difference divs can be set up with difference width, height, columns & style.

Thanks for your feedback.


Trying to elaborate:

If any of you know to programs like inDesign where you can create two text fields and link then together so that the text continues from the first text field to the next. And again you can link another to the collection and if the text is long enough it will start at textfield one go to the second and at end at the last:

These boxes can be placed all around the screen and the only thing they have together is that they share the same content.

Box 1
------------------------------
Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. 
Proin rutrum ligula nec quam 
molestie sed rutrum justo 
------------------------------

Box 2 
------------------------------ 
auctor. Quisque pulvinar diam 
nisl. Curabitur porttitor 
vehicula dui. Sed tempus 
venenatis est, non egestas 
------------------------------

Box 3
------------------------------ 
urna consequat a. Morbi diam 
mi, fermentum non lobortis 
eget, rhoncus id arcu. 

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

Upvotes: 18

Views: 1024

Answers (6)

Mark Leighton Fisher
Mark Leighton Fisher

Reputation: 5703

This is mostly the same as the read-buffer problem (i.e. reading a bunch of text, buffer-load by buffer-load, then parsing it out into other units (lines in the case of plain text)). A buffering layer between the data and the display code would help. (Sorry I don't have any code examples lying around.)

Upvotes: 1

Oleg
Oleg

Reputation: 24998

Your first layout may be achievable with CSS only (no JavaScript, no unsupported properties). You may not be able to accurately set the size of the boxes though, after all we'll fake it until the browsers make it.

Let's jump right into the fiddle - try resizing it etc. to get a feel for how it works.

Basically we're relying on float behaviour, this everywhere-supported often-abused property was originally built for paragraph text flowing around images. Now since we can make anything float, we'll just be floating your some other stuff here content! The rest of CSS is pure trickery - to make the floated content look like it's not part of the container. In practice you may prefer a "faux-content blocks" approach not unlike popular faux columns.

One issue is lack of control on where the content breaks - the separator has to be inserted directly into text. If the container width is fixed though, you may be able to insert the separator on the server side with a sufficient degree of accuracy (within a half line worth of text you want to break on).

Finally, here's the code:

.container {
    padding:10px;
    border:1px solid black;
    background: #ccc;
    text-align:justify;
}
.other-stuff {
    float:left;
    height:130px;
    width:100%;
    border-top:1px solid black;
    border-bottom:1px solid black;
    /*left and right margins are so negative to "cover up" .container border*/
    margin:10px -11px;
    /*and now padding to offset left and right negative margins*/
    padding:0 11px;
    /*pretend this is see-through*/
    background:#fff;
}

The markup is super simple - .other-stuff inside of .container, both filled up with dummy content for good measure. Et voila, notice how the text wraps nicely:

Seriously, who doesn't like kittens?

No luck trying to fake it with the css3 columns, except maybe column-gap could be useful with fake backgrounds (i.e. split the container in two columns with the gap being as wide as the separator content).

NB: please avoid using JS for this kind of content layout adjusement as it would result in a flash of unstyled content just beforehand. It would however be appropriate to use JS if the content is retrieved asynchronously w/AJAX - this way it could be processed before being appended to the page.

Upvotes: 3

Spadar Shut
Spadar Shut

Reputation: 15817

Guy, I guess you are talking about CSS Regions. This is a really cool feature but browser support is not perfect yet:

CSS Regions support chart from caniuse.com

Upvotes: 4

balpha
balpha

Reputation: 50948

Here's a solution that handles both the height not being a multiple of the line height, and the widths being different, based on your original.

jQuery(function($) {
  var content = $(".c1").html(),
      $elems = $("div").empty(),
      lineHeight = 20,
      offset = 0,
      wholeThing = $("<div />"),
      maxWidth = 0;
  $elems.each(function() { maxWidth = Math.max(maxWidth, $(this).width()); });

  $elems.each(function() { 
    var thisWidth = $(this).width(),
        thisHeight = $(this).height(),
        floatHeight = (thisHeight / lineHeight | 0) * lineHeight;

    wholeThing.append($("<div />").css({
      width: maxWidth - thisWidth,
      height: floatHeight,
      clear: "right",
      float: "right"}));
    if (thisHeight % lineHeight) {
        wholeThing.append($("<div />").css({
          width: maxWidth,
          height: thisHeight - floatHeight,
          clear: "right",
          float: "right"}));
      });
    }

  wholeThing.css("width", maxWidth).append(content);

  $elems.each(function() {

    var $content = wholeThing.clone().appendTo(this);

    $content.css({
      position: "absolute",
      left: 0,
      top: -offset
    });

    offset += $(this).height();
  });
});

It's the same approach you took, but takes it one step further. You created divs with the full text, positioning them inside the target divs, shifted upwards by the combined heights of all the previous containers in the "chain".

What I added was this:

  • The content div (called wholeThing, the one that's eventually multiplied and added to each container) has its width set to the highest width of all containers.

  • Along the right side of wholeThing, we put floated divs that make sure that the text is wrapped according to the applicable width. In the example, the first container has a width of 200 pixels, and the highest width (and thus the width of wholeThing) is 300px. Thus we place a floated div of 100 pixels width and with the same height as the first container (rounded down to full multiples of the line height) on the right edge. This solves the "different widths" problem.

  • After that, assuming the div's height is not a multiple of the line height, we add an extra full-width float to make sure we don't have a half line at the bottom, solving the line height problem.

The "rounding down to multiples of the line height" thing is only for some webkit browsers, because of this bug. This seems to have been fixed in Chrome, but I still see it in other browsers (notably, Safari 5 and the Android browser).

If this issue didn't exist, you could instead make the width-constraining div have the full height of the container (and not round down), and make the full-width div always have height 1 (and account for that extra pixel when incrementing offset). This would have the awesome advantage that you're not required to have a fixed line height. Here's an example – it works in Chrome, Firefox, Opera, and IE9+, but not in the above-mentioned webkit browsers. It also seems to work in IE8, though I haven't quite figured out why, since my first version (the one that works in Safari) breaks in IE8. To be honest, I didn't spend too much time on IE8 here.

So the top version should work in IE9+ and, well, all other browers, more or less.

As far as columns go, I don't see that happening (other than by essentially rebuilding the columns with divs).

Upvotes: 8

Andreas Louv
Andreas Louv

Reputation: 47117

The best I can come up with right now is: http://jsbin.com/iretip/3/edit

This will only work if:

The code is posted below, and the demo is located here:

  <div class="c1 c">
    Line 1<br />Line 2<br />Line 3<br />Line 4<br />Line 5<br />Line 6<br />Line 7<br />Line 8<br />Line 9<br />Line 10<br />Line 11<br />Line 12<br />Line 13<br />Line 14<br />Line 15<br />Line 16<br />Line 17<br />Line 18<br />Line 19<br />Line 20<br />Line 21<br />
  </div>
  <div class="c2 c"></div>
  <div class="c3 c"></div>

CSS:

.c {
  position: relative;
  line-height: 20px;
  overflow: hidden;
  width: 160px;
}

.c1 {
  height: 200px;
  background: yellow;
}
.c2 {
  position: absolute;
  top: 300px;
  height: 140px;
  background: blue;
}
.c3 {
  position: absolute;
  top: 300px;
  left: 200px;
  height: 200px;
  background: red;
}

And JavaScript:

jQuery(function($) {
  var content = $(".c1").html(),
      $elems = $("div").empty(),
      lineHeight = 20,
      offset = 0;

  $elems.each(function() {
    var $wrapper = $("<div/>").appendTo(this),
        $content = $("<div/>").html(content).appendTo($wrapper);

    $wrapper.css({
      position: "absolute",
      left: 0,
      top: -offset
    });

    offset += $(this).height();
  });
});

Upvotes: 3

Wesley Hales
Wesley Hales

Reputation: 61

Here it is with some simple JS. http://jsfiddle.net/wesleyhales/vsD3m/

HTML:

<div id="input">Line 1
Line 2
Line 3
Line 4</div>

<div id="box1">  
</div>
<hr/>
My content... more content.. and more content
<hr/>
<div id="box2">  
</div>

JS:

var myinput = document.getElementById('input').innerHTML;
var threshhold = 2;
var totalLines = myinput.split('\n');
for(var i = 0; i < totalLines.length; i++){
    if(i < threshhold){
       document.getElementById('box1').innerHTML += totalLines[i] + '\n'; 
    }else{
       document.getElementById('box2').innerHTML += totalLines[i] + '\n';  
    }    
} 

Overall, you have to have a source input, with all the lines. Then you need a threshold for each box - how many lines do you want in it? (or base threshold on box height or characters in lines, etc...). Then you need a target to distribute to when each threshold is met.

If this was available in CSS it would require a lot of upfront setup, but would be cool nonetheless.

Upvotes: 2

Related Questions