Skip to main content

The Mod Squad: Reusable style sheet components

Enabling a single style sheet for content tailoring

Brad Topol, Ph.D. (btopol@us.ibm.com), Senior Software Engineer, IBM
Brad Topol is a senior software engineer for IBM in Research Triangle Park, NC in the WebSphere Advanced Technology group. Currently, he is actively involved in advanced technology projects in the areas of transcoding, distributed systems, networking, and graphical user interfaces. Brad can be reached at btopol@us.ibm.com.
Steve Baber (scbaber@us.ibm.com), Senior Software Engineer, IBM
Steve Baber is a senior software engineer for IBM in Research Triangle Park, NC. Steve was formerly a member of the development team for the IBM WebSphere Transcoding Publisher product. Currently he is working in IBM's Pervasive Computing Division in the deployment of the WebSphere Everyplace Suite. Steve is a graduate of General Motors Institute of Technology, with a Masters degree from Case Western Reserve University. He can be reached at scbaber@us.ibm.com.

Summary:  The growing variety in personal digital assistants (PDAs) and cell phones presents new challenges in getting the appropriate look and feel for information displayed on these devices. In this article, Brad Topol and Steve Baber show how to write reusable, modular style sheet components that can be included by other style sheets, allowing a single style sheet to tailor content differently for different devices.

Date:  01 Jun 2001
Level:  Introductory
Activity:  441 views

Overview

The wide variety and breadth of handheld devices, such as PDAs and cell phones, has increased the complexity for tailoring content to meet the specific environment of the device display. This includes a variety of screen sizes, markup languages, and screen display capabilities. Where content is being generated with XSL style sheets, there is potential for an ever-expanding number of style sheets, one for each specific device and input source. In this article, we show how to write reusable, modular style sheet components that can be included by other style sheets and allow a single style sheet to tailor content differently for different devices.

We will show how to create a single style sheet that supports both HTML and WML, with the following features:

  • Generates either <b> tags for a WML device or <h1> tags for an HTML device
  • Generates a device-specific starting tag, such as <html> for HTML devices and <wml> for WML devices
  • Generates a device-specific body tag, such as <body> for HTML devices and <card> for WML devices
  • Makes a single table structure that creates a true table on devices where table layout is appropriate, and creates a list to render the content on smaller devices
  • Shows how to dynamically load content into a style sheet, avoiding hard coding content such as headers and footers into style sheets
Of course, you have to manage the generated style sheets at run-time too, and make sure the right style sheet -- for the right device -- gets applied for any given request.

IBM WebSphere Transcoding Publisher can do this for you in such a way that the XSLT transformations of your application are logically (and physically, if you like) separate from the business logic that produces the XML.

First we'll describe the individual reusable components, then show a developer's style sheet that includes the techniques and results.


Generating different tags for different situations

Our first reusable style sheet component lets you generate different elements (sometimes referred to as tags) for different situations. For example, to emphasize text, we might use <h1> elements for devices that accept HTML and <b> elements for devices that accept WML. You can create a reusable style sheet component for creating the appropriate tag for the selected device. First we created an XSL "bold" variable that can return either 'b' or 'h1'. It uses the deviceType parameter provided by WebSphere Transcoding Publisher to determine what type of string to return, and uses the xsl:choose element for implementation, as shown below.


XSL test for a specific device

<xsl:variable name="bold">
    <xsl:choose>
    <xsl:when test="$deviceType='WML Device'">b</xsl:when>
    <xsl:otherwise>h1</xsl:otherwise>
    </xsl:choose>
</xsl:variable>


We then used the xsl:element element in our style sheet to dynamically create an element based on the value of the bold variable, as follows.


Element substitution

<xsl:element name="{$bold}">
    <xsl:text>  Flight Info</xsl:text>
</xsl:element>

The example above shows how to create either an HTML <h1> tag or a WML <b> tag. Note, however, that the same technique is valuable when dealing only with a WML environment; phones that support WML differ slightly, and on some of them you should use a <b> tag while on others you should use an <em> tag. This technique could be used to create either a <b> tag or an <em> tag by changing the <h1> above to an <em>, and by using a user-agent parameter instead of a deviceType parameter (the user-agent value is also provided by WTP) as its means for determing what type of string to return.


Generating device-specific starting and body tags

In a similiar approach, we used a variable to create device-specific starting tags, such as such as <html> for HTML devices and <wml> for WML devices. Again we first created an XSL "startdocument" variable that can return either 'wml' or 'html'. It uses the deviceType parameter provided by WTP to determine what type of string to return, and uses the xsl:choose element to implement the function, as shown below.


Setting a variable based on device type

<xsl:variable name="startdocument">
    <xsl:choose>
    <xsl:when test="$deviceType='WML Device'">wml</xsl:when>
    <xsl:otherwise>html</xsl:otherwise>
    </xsl:choose>
</xsl:variable>

We then used the xsl:element element in our style sheet to dynamically create an element based on the value of the startdocument variable, as follows.


Element substitution

<xsl:element name="{$startdocument}">
<!-- Children elements go here -->
<!-- We denote the completion of the element 
                     with the following end tag -->
</xsl:element>

Similarly, we used a "body" variable to create device-specific starting tags, such as <body> for HTML devices and <card> for WML devices. Below is an example of this type of reusable component.


Start tag variable initialization

<xsl:variable name="body">
     <xsl:choose>
     <xsl:when test="$deviceType='WML Device'">card</xsl:when>
     <xsl:otherwise>body</xsl:otherwise>
     </xsl:choose>
</xsl:variable>

Like the previous example, we then used the xsl:element element in our style sheet to dynamically create an element based on the value of the body variable, show below.


Start tag substitution

<xsl:element name="{$body}">
<!-- Children elements go here -->
<!-- We denote the completion of the body element 
                          with the following end tag -->
</xsl:element>


Generating a multipurpose table structure

This section shows how to make a table structure that can create either a table or list, depending on device type. To do this, our reusable style sheet components must be able to:

  • Create a dynamic table tag that is truly a table tag for devices that support tables and is not a table tag for other devices
  • Create a dynamic table row tag (such as <tr>) that is truly a <tr> for devices that support tables and is not a <tr> tag for other devices
  • Create a dynamic table heading tag (such as <th>) that is truly a <th> for devices that support tables, and does nothing for devices that do not support tables
  • Create a dynamic table data tag (such as <td>) that is truly a <td> for devices that support tables, and for devices that do not support tables creates a nicely formatted list entry with labels added to make it easy to associate the entry with the respective column

Creating a dynamic table tag

To create a dynamic table tag, we again used a variable to create device-specific tags, such as <table> for HTML devices and <b> for WML devices. We created an XSL "table" variable that can return either 'table' or 'b'. We used the deviceType parameter provided by WTP to determine what type of string to return, and used the xsl:choose element for implementation, as follows.


Table tag variable initialization

<xsl:variable name="table">
     <xsl:choose>
     <xsl:when test="$deviceType='WML Device'">b</xsl:when>
     <xsl:otherwise>table</xsl:otherwise>
     </xsl:choose>
</xsl:variable>

Then, we could use the xsl:element element in our style sheet to dynamically create an element based on the value of the body variable, as shown below.


Table tag substitution

<xsl:element name="{$table}">
<!-- Children elements go here -->
<!-- We denote the completion of the table element 
                           with the following end tag -->
</xsl:element>

Creating a dynamic table row tag

To create a dynamic table row tag, we again used a variable to create device-specific tags, such as <tr> for HTML devices and <b> for WML devices. We created an XSL "tr" variable that can return either 'tr' or 'b'. We used the deviceType parameter provided by WTP to determine what type of string to return, and used the xsl:choose element for implementation, as shown below.


Table row variable initialization

<xsl:variable name="tr">
     <xsl:choose>
     <xsl:when test="$deviceType='WML Device'">b</xsl:when>
     <xsl:otherwise>tr</xsl:otherwise>
     </xsl:choose>
</xsl:variable>

We could then use the xsl:element element in our style sheet to dynamically create an element based on the value of the table row variable, as shown below.


Table row substitution

<xsl:element name="{$tr}">
<!-- Children elements go here -->
<!-- We denote the completion of the table row element 
                               with the following end tag -->
</xsl:element>

Creating a dynamic table heading tag

We created a table heading tag by making a new callable template instead of using techniques shown earlier, because our table heading is too complex for a single variable. Our table heading template has the value for the heading passed in as a label parameter, then wraps both a <th> and a <b> tag around the label content for HTML devices. For WML devices, it does absolutely nothing. The template below shows how to do this.


Callable template initialization

<xsl:template name="th">
  <xsl:param name="label" />
    <xsl:choose>
       <xsl:when test="$deviceType='WML Device'">
       </xsl:when>
       <xsl:otherwise>
       <th>
       <b>
       <xsl:value-of select="$label" />
       </b>
       </th>
       </xsl:otherwise>
       </xsl:choose>
   </xsl:template>

We then called this template from within our style sheet to dynamically create table headings, as follows.


Calling template for label substitution


<xsl:call-template name="th">
  <xsl:with-param name="label">City</xsl:with-param>
</xsl:call-template>

Creating a dynamic table data tag

We created a table data tag by making a new callable template, instead of using the dynamic variable techniques, because our table data is too complex for a single variable. The table data template creates a table data tag (such as <td>) that is truly a <td> for HTML devices that support tables. For WML devices that do not support tables (or, more precisely, do not support the full HTML function), the template creates a nicely formatted list entry with labels added to make it easy to recognize which column label value is associated with the entry. Do this by creating a table data template that has both the data value and the heading label passed into it.

The template then determines if the device is WML or HTML; it uses the deviceType parameter provided by WTP to determine what type of device is being used. If it's a WML device, the template first outputs the heading label and then outputs the data value below the label and indented two spaces. If it is an HTML device, the template simply outputs the data value enclosed by <td> tags. The template below shows how to do this.


Template to output table header values as labels for WML devic

<xsl:template name="td">
      <xsl:param name="value" />
      <xsl:param name="label" />

        <xsl:choose>
           <xsl:when test="$deviceType='WML Device'">
                  <xsl:value-of select="$label" /> 
                  <br /> 
                  <xsl:text>  </xsl:text><xsl:value-of select="$value" />
                  <xsl:text>  </xsl:text> <br />
           </xsl:when>
           <xsl:otherwise>
           <td>
           <xsl:value-of select="$value" />
           </td>                                                                  

           </xsl:otherwise>
           </xsl:choose>                                                          

</xsl:template>

We then called this template from within our style sheet to dynamically create table data elements, as follows.


Calling template for dynamic table data elements

<xsl:call-template name="td">
<xsl:with-param name="value" select="DepartingInfo/City" />
<xsl:with-param name="label">City</xsl:with-param>
</xsl:call-template>

Our example assumes that tables are usually appropriate for HTML devices and lists are usually appropriate for WML devices, but it's worth noting that WML devices vary greatly in screen size. Thus, when some WML devices should use the table structure and others should use the list structure you can use our approach and use a user-agent parameter instead of a deviceType parameter (provided by WTP) to determine what structure to create.


Dynamically loading content into a style sheet

In the following example we illustrate how to dynamically load content into a style sheet, thus avoiding hard coding content, such as headers and footers, directly into style sheets. It's advantageous to dynamically load this kind of content because when it needs updating it has to be done in only one place. Had we not used this approach, each and every style sheet that used headers and footers would need modification. This would become unmanageable once we had a lot of style sheets with headers and footers.

To exploit this technique, we first created an XML file with the content we wanted shared by several style sheets; the navigation.xml file shows that information below.


Sample input XML file

<?xml version="1.0" encoding="ISO-8859-1"?>
<navigation>
  <link url="http://link1.html">
   Application Page A
  </link>
  <link url="http://link2.html">
   Application Page B
  </link>
  <link url="http://link3.html">
   Application Page C
  </link>
</navigation>

This simple XML file has links and a textual description associated with each link. The links represent the footer information in all of our style sheets. To use this content in the style sheet, we created a reusable style sheet component that can dynamically load the content into the style sheet and format it as anchor tags, as shown in the following example.


Reusable style sheet component for adding anchor tags

<xsl:template name="footer">
           <xsl:for-each select="document('navigation.xml')/navigation/link">
           <br/>
           <a>
           <xsl:attribute name="href">
           <xsl:value-of select="@url" />
           </xsl:attribute>
           <xsl:value-of select="." /> </a>

           </xsl:for-each>
   </xsl:template>

As shown above, we used an xsl:for-each in conjunction with the XSL document function to load the link information. The rest of the template then formats the content as anchor tags. Thus, in the future to update the links to be added as footer information, all we do is update the navigation.xml file with the new links. Then all the applicable style sheets will pick up the updates automatically.


Putting it all together

First, the style sheet template.xsl, which contains all of the reusable style sheet components described above, is shown below.


Complete style sheet template "template.xsl"

 <?xml version="1.0"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:variable name="bold">
             <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">b</xsl:when>
             <xsl:otherwise>h1</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>                                                                   

        <xsl:variable name="startdocument">
             <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">wml</xsl:when>
             <xsl:otherwise>html</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>                                                                   

        <xsl:variable name="body">
             <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">card</xsl:when>
             <xsl:otherwise>body</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>                                                                   

        <xsl:variable name="table">
             <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">b</xsl:when>
             <xsl:otherwise>table</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>                                                                   

        <xsl:variable name="tr">
             <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">b</xsl:when>
             <xsl:otherwise>tr</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>                                                                   

        <xsl:template name="td">
        <xsl:param name="value" />
        <xsl:param name="label" />                                                         

          <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">
                   <xsl:value-of select="$label" />
                   <br />
                   <xsl:text>  </xsl:text><xsl:value-of select="$value" />
                   <xsl:text>  </xsl:text> <br />
             </xsl:when>
             <xsl:otherwise>
             <td>
             <xsl:value-of select="$value" />
             </td>                                                                         

             </xsl:otherwise>
             </xsl:choose>                                                                 

         </xsl:template>                                                                   

       <xsl:template name="th">
        <xsl:param name="label" />
          <xsl:choose>
             <xsl:when test="$deviceType='WML Device'">
             </xsl:when>
             <xsl:otherwise>
             <th>
             <b>
             <xsl:value-of select="$label" />
             </b>
             </th>
             </xsl:otherwise>
             </xsl:choose>                                                                 

         </xsl:template>                                                                   

       <xsl:template name="footer">
             <xsl:for-each select="document('navigation.xml')/navigation/link">
             <br/>
             <a>
             <xsl:attribute name="href">
             <xsl:value-of select="@url" />
             </xsl:attribute>
             <xsl:value-of select="." /> </a>

             </xsl:for-each>
         </xsl:template>                                                                   

 </xsl:stylesheet>

The next single style sheet, which includes template.xsl, can be used as a single style sheet to generate different types of output.


Run time style sheet "flightinfo.xsl"

<?xml version="1.0"?>

<!-- Change Flight Information from Flights DTD to WML -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output doctype-system="http://www.wapforum.org/DTD/wml_1.1.xml"/>
<xsl:param name="deviceType" select="defaultValue" />
<xsl:include href="template.xsl"/>

	<xsl:template match="/">
        <xsl:element name="{$startdocument}">
        <xsl:element name="{$body}">
                        <p>
			<xsl:text>
                        </xsl:text>

			<xsl:text>
                        </xsl:text>
                           <xsl:element name="{$bold}">
                             <xsl:text>  Flight Info</xsl:text>
                           </xsl:element>
                           <br/>
                           <xsl:element name="{$table}">
                             <xsl:if test="$table='table'">
                                <xsl:attribute name="border">2</xsl:attribute>
                             </xsl:if>
			     <xsl:apply-templates/>
			   </xsl:element>

               <xsl:call-template name="footer" />
                        </p>
                        </xsl:element>
                        </xsl:element>
	</xsl:template>

	<xsl:template match="Flights">

                    <xsl:element name="{$tr}">
                    <xsl:call-template name="th">
                    <xsl:with-param name="label">City</xsl:with-param>
                    </xsl:call-template>

                    <xsl:call-template name="th">
                    <xsl:with-param name="label">Time</xsl:with-param>
                    </xsl:call-template>

                    <xsl:call-template name="th">
                    <xsl:with-param name="label">Gate</xsl:with-param>
                    </xsl:call-template>
                    </xsl:element>

		<xsl:for-each select="FlightSegment">

		    <xsl:text>
                    </xsl:text>

                    <xsl:element name="{$tr}">

                    <xsl:call-template name="td">
                    <xsl:with-param name="value" select="DepartingInfo/City" />
                    <xsl:with-param name="label">City</xsl:with-param>
                    </xsl:call-template>

                    <xsl:call-template name="td">
                    <xsl:with-param name="value" select="DepartingInfo/Time" />
                    <xsl:with-param name="label">Time</xsl:with-param>
                    </xsl:call-template>

                    <xsl:call-template name="td">
                    <xsl:with-param name="value" select="DepartingInfo/Gate" />
                    <xsl:with-param name="label">Gate</xsl:with-param>
                    </xsl:call-template>

	            </xsl:element>
 		</xsl:for-each>
       </xsl:template>

</xsl:stylesheet>

When building your style sheets using callable templates, you may sometimes want to extend the final "fit and polish" of the returned elements, as shown in the above example where a border element is added to the HTML table instance. Repeated here is the simple test for a returned table element and the addition of the border element and associated attribute.


Test to add border to table element

   ....
  <xsl:element name="{$table}">
  <xsl:if test="$table='table'">
  <xsl:attribute name="border">2</xsl:attribute></xsl:if>
  <xsl:apply-templates/>
  </xsl:element>
....                      

We next provided a sample XML file within an inline document type definition (DTD) containing sample data about airline flight schedules. The following is used for application of the above style sheet.


Sample input XML file

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Flights [
  <!ELEMENT Flights (AirCarrier, FlightNumber, FlightSegment*)*>
  <!ELEMENT FlightSegment (DepartingInfo, ArrivingInfo)?>
  <!ELEMENT DepartingInfo (City,Date,Scheduled,
       Status?,Time?,Terminal?,Gate?,OffGateTime?,OffGroundTime?)?>
  <!ELEMENT ArrivingInfo (City,Date,Scheduled,
       Status?,Time?,Terminal?,Gate?,Baggage?,OnGroundTime?,OnGateTime?)?>
  <!ELEMENT FlightNumber (#PCDATA)>
  <!ELEMENT AirCarrier (#PCDATA)>
  <!ELEMENT Date (#PCDATA)>
  <!ELEMENT City (#PCDATA)>
  <!ELEMENT Scheduled (#PCDATA)>
  <!ELEMENT Time (#PCDATA)>
  <!ELEMENT Status (#PCDATA)>
  <!ELEMENT Terminal (#PCDATA)>
  <!ELEMENT Gate (#PCDATA)>
  <!ELEMENT Baggage (#PCDATA)>
  <!ELEMENT OffGroundTime (#PCDATA)>
  <!ELEMENT OffGateTime (#PCDATA)>
  <!ELEMENT OnGroundTime (#PCDATA)>
  <!ELEMENT OnGateTime (#PCDATA)>
]>
<Flights>
  <AirCarrier>AA</AirCarrier>
  <FlightNumber>700</FlightNumber>
  <FlightSegment>
    <DepartingInfo>
      <City>DFW</City>
      <Date>31Mar</Date>
      <Scheduled>0630A</Scheduled>
      <Status>ON TIME</Status>
      <Time>0632A</Time>
      <Gate>C16</Gate>
      <OffGateTime>0644A</OffGateTime>
      <OffGroundTime>0632A</OffGroundTime>
    </DepartingInfo>
    <ArrivingInfo>
      <City>LGA</City>
      <Date>31Mar</Date>
      <Scheduled>1040A</Scheduled>
      <Status>ON TIME</Status>
      <Time>1043A</Time>
      <Gate>D5</Gate>
      <Baggage>B</Baggage>
      <OnGroundTime>1043A</OnGroundTime>
    </ArrivingInfo>
  </FlightSegment>
  <FlightSegment>
    <DepartingInfo>
      <City>LGA</City>
      <Date>31Mar</Date>
      <Scheduled>1050A</Scheduled>
      <Status>ON TIME</Status>
      <Time>1050A</Time>
      <Gate>C18</Gate>
      <OffGateTime>1100A</OffGateTime>
      <OffGroundTime>1130A</OffGroundTime>
    </DepartingInfo>
    <ArrivingInfo>
      <City>RDU</City>
      <Date>31Mar</Date>
      <Scheduled>145P</Scheduled>
      <Status>ON TIME</Status>
      <Time>150P</Time>
      <Gate>A5</Gate>
      <Baggage>3</Baggage>
      <OnGroundTime>150P</OnGroundTime>
    </ArrivingInfo>
  </FlightSegment>
</Flights>

Finally, here's the different types of output created for the different device types:


Flight info on Netscape
Flight info on Netscape

HTML produced by this example:

 <html><body><p><h1>  Flight Info</h1> 
 <br><table border="2"><tbody><tr><th><b>City</b>
 </th>
 <th><b>Time</b>
 </th>
 <th><b>Gate</b>
 </th>
 </tr>
 <tr><td>DFW</td>
 <td>0632A</td>
 <td>C16</td>
 </tr>
 <tr><td>LGA</td>
 <td>1050A</td>
 <td>C18</td>
 </tr>
 </tbody>
 </table>
 <br><a href="http://link1.html">   Application Page A
   </a>
 <br><a href="http://link2.html">   Application Page B
   </a>
 <br><a href="http://link3.html">   Application Page C
   </a> 
 </body>
 </html>

The following sequence shows the individual portions as they appear in a WAP phone:

WAP phone output WAP phone output WAP phone output
WAP phone output WAP phone output


WML produced by this example:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" 
             "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
  <card>
    <p>
      <b> Flight Info</b>
      <br/>
      <b>
        <b/>
        <b>
          City
          <br/>
            DFW  
          <br/>
          Time
          <br/>
            0632A  
          <br/>
          Gate
          <br/>
            C16  
          <br/>
        </b>
        <b>
          City
          <br/>
            LGA  
          <br/>
          Time
          <br/>
            1050A  
          <br/>
          Gate
          <br/>
            C18  
          <br/>
        </b>
      </b>
    </p>
  </card>
</wml>

Conclusion

Reusable style sheet components can be included by other style sheets, allowing a single style sheet to tailor content differently for different devices. We hope you find this a useful technique in creating style sheets that support both HTML and WML.


Resources

  • Refer to the developerWorks XML zone for information about using XML.

  • You might be interested in other developerWorks articles on related topics:

  • For more information on XML, see W3C Architecture domain.

  • For information on XSL-T, see:

  • Solutions 2001 offers the following related sessions:

About the authors

Brad Topol, Ph.D.

Brad Topol is a senior software engineer for IBM in Research Triangle Park, NC in the WebSphere Advanced Technology group. Currently, he is actively involved in advanced technology projects in the areas of transcoding, distributed systems, networking, and graphical user interfaces. Brad can be reached at btopol@us.ibm.com.

Steve Baber is a senior software engineer for IBM in Research Triangle Park, NC. Steve was formerly a member of the development team for the IBM WebSphere Transcoding Publisher product. Currently he is working in IBM's Pervasive Computing Division in the deployment of the WebSphere Everyplace Suite. Steve is a graduate of General Motors Institute of Technology, with a Masters degree from Case Western Reserve University. He can be reached at scbaber@us.ibm.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Sample IT projects
ArticleID=10077
ArticleTitle=The Mod Squad: Reusable style sheet components
publish-date=06012001
author1-email=btopol@us.ibm.com
author1-email-cc=
author2-email=scbaber@us.ibm.com
author2-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).