Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining width of a printed string by a webapp

In my (PHP) web app, I have a part of my site that keeps a history of recent searches. The most recent queries get shown in a side box. If the query text is too long, I truncate it and show ellipses. Eg: "My very long query is..."

Currently, I truncate after a certain number of characters. Since the font is not monotype, a query of all I's is more narrow than a query of all W's. I'd like them to all be about the same width prior to the ellipses. Is there a way to get the approximate width of the resulting string so that the ellipses for any given string will occur in about the same number of pixels from the beginning? Does CSS have a way? Does PHP? Would this be better handled by JavaScript?

like image 644
Dinah Avatar asked Aug 29 '08 02:08

Dinah


1 Answers

Here's another take on it and you don't have to live without the ellipsis!

<html>
<head>

<style>
div.sidebox {
    width: 25%;
}

div.sidebox div.qrytxt {
    height: 1em;
    line-height: 1em;
    overflow: hidden;
}

div.sidebox div.qrytxt span.ellipsis {
    float: right;
}
</style>


</head>

<body>

<div class="sidebox">
    <div class="qrytxt">
        <span class="ellipsis">&hellip;</span>
        Some long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
    </div>
    <div class="qrytxt">
        <span class="ellipsis">&hellip;</span>
        Some more long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
    </div>
    <div class="qrytxt">
        <span class="ellipsis">&hellip;</span>
        Short text. Fail!
    </div>
</body>

</html>

There is one flaw with this, if the text is short enough to be fully displayed, the ellipses will still be displayed as well.

[EDIT: 6/26/2009]

At the suggestion of Power-Coder I have revised this a little. There are really only two changes, the addition of the doctype (see notes below) and the addition of the display: inline-block attribute on the .qrytxt DIV. Here is what it looks like now...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <style>
        div.sidebox 
        {
            width: 25%;
        }

        div.sidebox div.qrytxt
        {
            height: 1em;
            line-height: 1em;
            overflow: hidden;
            display: inline-block;
        }

        div.sidebox div.qrytxt span.ellipsis
        {
            float: right;
        }
</style>
</head>

<body>
    <div class="sidebox">
        <div class="qrytxt">
            <span class="ellipsis">&hellip;</span>
            Some long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
        </div>

        <div class="qrytxt">
            <span class="ellipsis">&hellip;</span>
            Some more long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
        </div>

        <div class="qrytxt">
            <span class="ellipsis">&hellip;</span>
            Short text. FTW
        </div>
    </div>
</body>
</html>

Notes:

  • Viewed in IE 8.0, Opera 9, FF 3

  • A doctype is required for IE to get the display: inline-block to work correctly.

  • If the .qrytxt DIV's overflow occurs on a long word, there is going to be a wide gap between the ellipsis and the last visible word. You can see this by viewing the example and resizing your browser width in small increments. (this probably existed in the original example as well, I just may have not noticed it then)

So again, an imperfect CSS-only solution. Javascript may be the only thing that can get the effect perfect.

[EDIT: 6/27/2009]

Here is another alternative which uses browser specific extensions.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
    <style>
        div.sidebox 
        {
            width: 26%;
        }

        div.sidebox div.qrytxt
        {
            height: 1em;
            line-height: 1em;
            overflow: hidden;
            text-overflow:ellipsis;
            -o-text-overflow:ellipsis;
            -ms-text-overflow:ellipsis;
            -moz-binding:url(ellipsis-xbl.xml#ellipsis);
            white-space:nowrap;
        }
    </style>
</head>

<body>
    <div class="sidebox">
        <div class="qrytxt">
            Some long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
        </div>

        <div class="qrytxt">
            Some more long text which will arbitrarily be cut off at whatever word fits best but will have an ellipsis at the end.
        </div>

        <div class="qrytxt">
            Short text. FTW
        </div>
    </div>
</body>
</html>

Note that in order for the above example to work, you must create the xml file referenced by the -moz-binding rule, ellipsis-xbl.xml. It's should contain the following xml:

<?xml version="1.0" encoding="UTF-8"?>
  <bindings xmlns="http://www.mozilla.org/xbl" xmlns:xbl="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <binding id="ellipsis">
      <content>
        <xul:window>
          <xul:description crop="end" xbl:inherits="value=xbl:text"><children/></xul:description>
        </xul:window>
      </content>
    </binding>
  </bindings>
like image 197
Robert Groves Avatar answered Sep 22 '22 18:09

Robert Groves