Jump to content

PHP/HTML Tables w/ Rounded Corners + Anti-Aliasing


monkey_05_06

Recommended Posts

When I decided I wanted to make a table with rounded corners, I just looked up on Google how other sites had done it with CSS. To my horror however I realized that these methods required a "background" color to be set for the area "behind" the rounded corners, while all it was really doing was drawing the so-called "background" color on top of the table.

That's really not what I wanted it to do since I have a background image on my pages, not a solid background color. So after considering my alternatives, I decided to write my own script. The end result...this:

[code]<?php
  // roundedtables.php
  function is_char($var) { // returns whether VAR is a char variable (i.e., whether it is a number between 0 and 255 inclusive)
    return (($var >= 0) && ($var <= 255));
    }

  function charval($var) { // represents VAR as a char variable (i.e., its integer value will be forced to a range between 0 and 255 inclusive)
    if (is_char($var)) return $var;
    $i = intval($var);
    for (; $i < 0; $i += 256);
    for (; $i > 255; $i -= 256);
    return $i;
    }

  function hex2rgb($hex) { // returns an array containing HEX as RGB values with indices 0/"r", 1/"g", 2/"b"
    // valid values for HEX are hexadecimal literals (i.e., 0x0c2f33 (798515 in regular decimal)) or hexadecimal formatted strings with a #, &H, or 0x prefix
    if (!is_string($hex)) $hex = sprintf("%06X", $hex); // accept raw hex input and string input with #, &H, or 0x identifiers
    if ($hex[0] === "#") $hex = substr($hex, 1);
    else if ((strpos($hex, "&H") === 0) || (strpos($hex, "0x") === 0)) $hex = substr($hex, 2);
    $hex = sprintf("%06s", $hex);
    $cutpoint = ceil(strlen($hex) / 2) - 1;
    $rgb = explode(":", wordwrap($hex, $cutpoint, ":", ($cutpoint)), 3);
    $rgb[0] = (isset($rgb[0]) ? hexdec($rgb[0]) : 0);
    $rgb[1] = (isset($rgb[1]) ? hexdec($rgb[1]) : 0);
    $rgb[2] = (isset($rgb[2]) ? hexdec($rgb[2]) : 0);
    $rgb["r"] = $rgb[0];
    $rgb["g"] = $rgb[1];
    $rgb["b"] = $rgb[2];
    return $rgb;
    }

  function css_opacity_str($opacity) { // returns a string containing the CSS to set OPACITY opacity for the current element
    if ($opacity !== intval(floatval($opacity))) $opacity = intval($opacity * 100);
    $str = "filter: alpha(opacity={$opacity}); ";
    $opacity = floatval($opacity / 100);
    $str .= "-moz-opacity: {$opacity}; ";
    $str .= "opacity: {$opacity}; ";
    $str .= "-khtml-opacity: {$opacity};";
    return $str;
    }

  $rounded_tables = array();
  $rounded_tables_rows_opacity = array(array(30, 70, 90), array(50, 70, 90), array(50, 70, 90), array(30, 70, 90), array(70, 90));

  function rounded_table_start($width, $r, $g, $b, $css_class = "") { // start a table with width WIDTH, background color of RGB, and of the CSS_CLASS class
    $width = intval($width);
    $r = charval($r);
    $g = charval($g);
    $b = charval($b);
    $rgb_str = "rgb(" . $r . "," . $g . "," . $b . ")";
    global $rounded_tables;
    array_push($rounded_tables, compact("width", "rgb_str", "css_class"));
    global $rounded_tables_rows_opacity;
    $rows_opacity = $rounded_tables_rows_opacity;
    for ($i = 0, $rows_op_size = sizeof($rows_opacity); $i < $rows_op_size; $i++) {
      $offset = (($width - ($width - (($rows_op_size - $i) - 2))) >= 0 ? ($width - ($width - (($rows_op_size - $i) - 2))) : 0);
      ?>
      <div class = "<?php echo $css_class; ?>" style = "display: block; height: 1px; position: relative; left: <?php echo $offset; ?>;">
        <?php
        for ($j = 0, $size = sizeof($rows_opacity[$i]); $j < $size; $j++) {
          ?>
          <span style = "overflow: hidden; float: left; width: 1px; height: 1px; background-color: <?php echo $rgb_str; ?>; <?php echo (is_array($rows_opacity[$i]) ? css_opacity_str($rows_opacity[$i][$j]) : css_opacity_str($rows_opacity[$i])); ?>">&nbsp;</span>
          <?php
          }
        ?>
        <span style = "overflow: hidden; float: left; width: <?php echo $width - (2 * (sizeof($rows_opacity[$i]) + $offset)); ?>px; height: 1px; background-color: <?php echo $rgb_str; ?>;">&nbsp;</span>
        <?php
        for ($j = sizeof($rows_opacity[$i]) - 1; $j >= 0; $j--) {
          ?>
          <span style = "overflow: hidden; float: left; width: 1px; height: 1px; background-color: <?php echo $rgb_str; ?>; <?php echo (is_array($rows_opacity[$i]) ? css_opacity_str($rows_opacity[$i][$j]) : css_opacity_str($rows_opacity[$i])); ?>">&nbsp;</span>
          <?php
          }
        ?>
      </div>
      <?php
      }
    ?>
    <table class = "<?php echo $css_class; ?>" style = "width: <?php echo $width; ?>px; background-color: <?php echo $rgb_str; ?>;">
    <?php
    }

  function rounded_table_start_hex($width, $rgb_hex, $css_class = "") { // synonym for rounded_table_start but takes a hex-formatted RGB parameter instead R, G, and B parameters
    // valid values for RGB_HEX are hexadecimal literals, i.e., 0x0c2f33 (798515 in regular decimal) or hexadecimal formatted strings with a #, &H, or 0x prefix
    $rgb_hex = hex2rgb($rgb_hex);
    rounded_table_start($width, $rgb_hex["r"], $rgb_hex["g"], $rgb_hex["b"], $css_class);
    }

  function rounded_table_end() { // ends the most recently opened started table
    global $rounded_tables;
    $arr = array_pop($rounded_tables);
    if ($arr === NULL) return;
    extract($arr);
    ?>
    </table>
    <?php
    global $rounded_tables_rows_opacity;
    $rows_opacity = array_reverse($rounded_tables_rows_opacity);
    for ($i = 0, $rows_op_size = sizeof($rows_opacity); $i < $rows_op_size; $i++) {
      $offset = ($i - 1 >= 0 ? $i - 1 : 0);
      ?>
      <div class = "<?php echo $css_class; ?>" style = "display: block; height: 1px; position: relative; left: <?php echo $offset; ?>">
        <?php
        for ($j = 0, $size = sizeof($rows_opacity[$i]); $j < $size; $j++) {
          ?>
          <span style = "overflow: hidden; float: left; width: 1px; height: 1px; background-color: <?php echo $rgb_str; ?>; <?php echo (is_array($rows_opacity[$i]) ? css_opacity_str($rows_opacity[$i][$j]) : css_opacity_str($rows_opacity[$i])); ?>">&nbsp;</span>
          <?php
          }
        ?>
        <span style = "overflow: hidden; float: left; width: <?php echo $width - (2 * (sizeof($rows_opacity[$i]) + $offset)); ?>px; height: 1px; background-color: <?php echo $rgb_str; ?>;">&nbsp;</span>
        <?php
        for ($j = sizeof($rows_opacity[$i]) - 1; $j >= 0; $j--) {
          ?>
          <span style = "overflow: hidden; float: left; width: 1px; height: 1px; background-color: <?php echo $rgb_str; ?>; <?php echo (is_array($rows_opacity[$i]) ? css_opacity_str($rows_opacity[$i][$j]) : css_opacity_str($rows_opacity[$i])); ?>">&nbsp;</span>
          <?php
          }
        ?>
      </div>
      <?php
      }
    }
  ?>[/code]

Save that as [color=green]roundedtables.php[/color] and then you can do this:

[code]<?php
  include("./roundedtables.php");
  rounded_table_start(250, 0, 204, 0);
  echo "<tr><td>This table has rounded corners. Awesome!</td></tr>";
  rounded_table_end();
  ?>[/code]

The first parameter for [color=green]rounded_table_start[/color] is the width of the table. The next three parameters are the R, G, and B parameters respectively. There is also an optional CSS class parameter so you can set the class of the table. This function prints out the table's header (this is a series of DIVs and SPANs that give it the rounded corners) as well as the opening TABLE HTML tag.

After calling [color=green]rounded_table_start[/color] you can put whatever information you want in the table, just like you would as if you had directly typed the opening TABLE tag yourself.

When you're ready to close the table you can call [color=green]rounded_table_end[/color] which will pring the closing TABLE tag as well as the table's footer DIVs and SPANs.

There is also [color=green]rounded_table_start_hex[/color] which is a synonym for [color=green]rounded_table_start[/color] with the exception that instead of taking R, G, and B parameters it accepts a single RGB_HEX parameter. This can be either a hexadecimal literal such as 0x00FF00 (bright green) or a hex-formatted string (this can be something like "00FF00", "#00FF00", "&H00FF00", or "0x00FF00" (all evaluating to bright green)).

Additionally you can override the default anti-aliasing method by changing the array [color=green]$rounded_tables_rows_opacity[/color]. The way that works is a bit complicated, so I'll explain it. For each element in the array a new row will be created in your table's header and footer sections. If the element is an array each of its elements will be read out and applied to their owning element's respective row. If it isn't an array, it will be applied directly. The way the elements are applied is that at each end of the row, a single pixel will be drawn in the opacity defined by that element. Now that's a bit confusing, so maybe an example would be better.

Let's take the default settings for the array as an example:

[code]  $rounded_tables_rows_opacity = array(array(30, 70, 90), array(50, 70, 90), array(50, 70, 90), array(30, 70, 90), array(70, 90));[/code]

The [color=green]$rounded_tables_rows_opacity[/color] array has 5 elements. That will translate to a 5px tall header and footer added onto your table. The first element is an array with 3 elements: 30, 70, and 90. So on the first row of your table's header it will draw a pixel at 30% opacity, another at 70% opacity, and finally a third at 90% opacity. It will then fill the row at 100% opacity and add 90%, 70%, and 30% opacity pixels to the end of the row, respectively.

Hopefully that explains the completely arbitrary anti-aliasing method I've implemented. And hopefully someone will find this useful. Feel free to let me know if you have any problems or just what you think about my script! Phew that was a lot.

monkey_05_06

Oh...BTW...this will actually add a lot of code to your HTML...so if you're concerned by that you might want to be wary of using this script.
Link to comment
Share on other sites

Well I don't have Flash or anything like that to make an animated demo, but I uploaded a page [url=http://www.meleepta.com/rtableex.php]here[/url] that contains two tables. The exact source is as follows:

[code]<html>
  <head>
    <title>The M&ecirc;l&eacute;e Island PTA - Rounded Tables Example</title>
  </head>
    <?php
      include("./roundedtable.php");
      rounded_table_start(250, 0, 204, 0);
      echo "<tr><td>This table has rounded corners. Awesome!</td></tr>";
      rounded_table_end();
      ?>
    <br />
    <br />
    <?php
      rounded_table_start_hex(375, 0xDA0000);
      echo "<tr><td>This is another...</td></tr>";
      rounded_table_end();
      ?>
  </body>
</html>[/code]
Link to comment
Share on other sites

looks useful, if limited. if you could make the 'rounded_table_start' more generic and useful for all types of containers, like DIV's, etc, that would be good. also - consider the last (optional) parameter of the rounded_table_start. if instead of 'css_class', you accepted an array of params, the user could ALSO tweak other standard parts of the table - cellpadding, cellspacing, etc, and the width could also be combined into it.

otherwise, good work. i know how tricky it can be to get perfect rounded corners with CSS...
Link to comment
Share on other sites

@redbull:

You're thinking something along the lines of:

array("width" => 250, "cellpadding" => 0, "cellspacing" => 0, "class" => "news")

For the array? I think that's reasonable...I would of course have to either specify a default width or abort the script if the width wasn't supplied. Not that that would be a problem, just something I would need to keep in mind.

Also what kind of containers would you like to see this applied to? DIVs...SPANs are inline so that wouldn't really make much sense...unless I forced it to be displayed as a block-level element. Off the top of my head I'm unsure what other containers you might like to apply it to, but do feel free to elaborate ;)

Thanks for the suggestion...I'll see what can be done about generalizing these functions.

@ober I know it's a lot of output...but I don't know of any better way to achieve the same effect. Feel free to let me know if you do :). And...what changes will CSS3 make that would affect this? I'd love to know!

monkey_05_06
Link to comment
Share on other sites

The old method uses only CSS and so it has to put DIVs on top of the TABLE to create the illusion of rounded corners. These DIVs must have a background color set manually, so that if you have a background image for that area, you cannot see it behind the rounded corners.

The newer methods use JavaScript which I'd rather not do :P. Also I've never liked relying on other people's coding. I'd just much rather do things myself. That way I learn...and if something gets screwed up 1) it's my fault, and 2) I have to either learn how to fix it or work around it. ;)
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.