KingKongFrog
KingKongFrog

Reputation: 14419

How do I keep a div from wrapping, when the div aligned to it can vary in it's width?

I have a simple setup. A div that contains a title and titleOptions.

The title sometimes is long and I would like it to have an ellipsis instead of showing the full title. To the right of the title is titleOptions. These can vary. Sometimes delete, edit and move, sometimes a few those, sometimes none. (The title width therefore cannot be fixed, since the titleOptions vary).

How do I ALWAYS have one line for the title and titleOptions. I don't want it to wrap ever, or push the titleOptions below.

I prefer the titleOptions width be fluid, since that would allow a longer title to have more real estate.

Here is a fiddle for a better explanation: http://jsfiddle.net/K8s3Z/1

Upvotes: 12

Views: 357

Answers (5)

user2678335
user2678335

Reputation:

just make the container div's width auto

Upvotes: 1

kalley
kalley

Reputation: 18462

You can use flexbox.

.titleBar {
    width:980px;
    overflow:hidden;
    border: 1px solid #EEE;
    margin-bottom:2em;
    display: -webkit-flex;
}
.title {
    border: 1px solid #DDD;
    white-space:nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-flex: 1;
}

.titleOptions {
    white-space:nowrap;
    border: 1px solid #DDD;
}

fiddle (which also has other syntax and prefixes needed, etc).


With JS if flexbox is not available

function getByClassName(collection, className) {
    var i = collection.length;
    var regexp = new RegExp('\\b' + className + '\\b');
    var returnSet = [];
    while ( i-- ) {
        if ( collection[i].className.match(regexp)  ) {
            returnSet.push(collection[i]);
        }
    }
    return returnSet;
}
if ( ! Modernizr.flexbox && ! Modernizr.flexboxlegacy ) {
    var bars = document.querySelectorAll('.titleBar');
    for (var i = 0, l = bars.length; i < l; ++i) {
        var bar = bars[i];
        var divs = bar.getElementsByTagName('*');
        var optWidth = getByClassName(divs, 'titleOptions')[0].offsetWidth;
        getByClassName(divs, 'title')[0].style.width = bar.offsetWidth - optWidth + 'px';
    }
}

The fiddle has custom functions for checking for flexbox (based on Modernizr) if you don't want to use Modernizr (for some reason). Just assigning those responses to a local object Modernizr in the fiddle. Also, no jQuery, in case you have an aversion to that as well. Both are easy to replace in here, if you're using them.

Upvotes: 10

Hugo Silva
Hugo Silva

Reputation: 6948

If you put you options container at the same level as the text and float it, the text should automatically wrap around the container. With a few adjustments you can display one line only and hide the rest.

Try this html:

<div class="titleBar">
    <div class="title"><div class="titleOptions">OPTIONS | CLICK ME</div> THIS IS MY TITLE </div>
</div>

And css:

.titleBar {
    border: 1px solid #EEE;
    margin-bottom:2em;
}

.title {
    overflow:hidden;
    white-space:nowrap;
    text-overflow: ellipsis;
}

.titleOptions {
    float:right;
    white-space:nowrap;
    border: 1px solid #DDD;
}

As a fallback for IE, you could drop the text overflow property on .title and use this instead

/*IE Fallback*/
.titleOptions {
    background-color:white;
    position:relative;
    z-index:10;
}
.titleOptions:before {
  content: "\2026 ";
  padding-right: 5px;
}

Upvotes: 1

doitlikejustin
doitlikejustin

Reputation: 6353

Here is an option using positioning (CSS only & all browsers supported minus the box-shadow) and even has a nice blending of the text.

Fiddle

.titleBar {
    width:980px;
    overflow:hidden;
    border: 1px solid #EEE;
    margin-bottom:2em;
    position: relative;
}

.title {
    float:left;
    border: 1px solid #DDD;

    overflow:hidden;
    white-space:nowrap;
}

.titleOptions {
    border: 1px solid #DDD;
    position: absolute;
    right: 0;
    top: 0;
    background-color: #fff;

    /* optional... make it blend in instead of ellipsis */
    -moz-box-shadow:    2px 0 25px 50px #fff;
    -webkit-box-shadow: 2px 0 25px 50px #fff;
    box-shadow:         2px 0 25px 50px #fff;     
}

Screenshot of blending... incase you didn't catch it.

Upvotes: 4

Nick Rolando
Nick Rolando

Reputation: 26167

To show an ellipsis, you can use the css text-overflow. Though AFAIK, you need to give the container a width so it is aware of where the overflow will occur at.

This CSS property doesn't force an overflow to occur; to do so and make text-overflow to be applied, the author must apply some additional properties on the element, like setting overflow to hidden.

You could run some javascript code after the DOM has loaded to dynamically set the width of .title based on the width of .titleOptions.

Here is a static example of what you're trying to do:

.title {
    float:left;
    border: 1px solid #DDD;
    white-space:nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 76%;
}

Try using js to set width dynamically.

Edit: Here is an example of how you can set width dynamically using javascript (and a little jQuery). Using the css for .title I have above (minus the width: 76%;), I added this js:

function getChildByClassName(ele, className) {
    for(var i = 0; i < ele.childNodes.length; i++) {
        if($(ele.childNodes[i]).hasClass(className)) {
            return ele.childNodes[i];
        }
    }
}

var titleBars = document.getElementsByClassName('titleBar');
var w = 0;
var spacer = 10;

for(var i = 0; i < titleBars.length; i++) {
    w = titleBars[i].clientWidth;
    w = w - getChildByClassName(titleBars[i], 'titleOptions').clientWidth - spacer;
    $(titleBars[i]).children('.title').eq(0).css('width', w + 'px');
}

http://jsfiddle.net/K8s3Z/8/

Upvotes: 9

Related Questions