The various selectors available in CSS2 give authors the ability to match practically any element in a given document. Using descendant selectors, child selectors, adjacent sibling selectors, and the first-child pseudo class in combination allows an author to dispense with id and class attributes in elements they wish to style. This can sometimes be very useful, as in styling table cells or list items for example.

Unfortunately (and it is a vexing inadequacy), a good number of browsers in popular use today do not yet implement these selectors. The only major browsers today that support all the above selectors are Netscape 6.x and 7 and IE5.x/Mac. Even Opera6/Win still does not recognize the first-child pseudo class which is imperative when trying to match an element that has many siblings (as in the table example below).

Be that as it may it is hoped that the next generation of browsers (the 7.x of IE and Opera for Windows for instance) will finally have the level of CSS implementation as Gecko based browsers (Netscape, Mozilla, K-Meleon, Phoenix, DocZilla, etc.).

To showcase the power of selectors let us try styling a table with many cells without resorting to classes and id's in the tr and td elements. Let's use a simple table marked up as follows:

<table summary="test table">
	<!-- rest of the table here -->

All the various changes in colors and background colors in the table below were done using CSS that have selectors which do not rely on attributes. Numbers refer to the cell's position and are in the format: [row,column]

As stated above only certain browsers implement all types of selectors. Therefore, you may or may not see all the styling in the table below. So here's a rundown of what ought to be rendered:

1,1 1,2 1,3 1,4 1,5 1,6 1,7
2,1 2,2 2,3 2,4 2,5 2,6 2,7
3,1 3,2 3,3 3,4 3,5 3,6 3,7
4,1 4,2 4,3 4,4 4,5 4,6 4,7
5,1 5,2 5,3 5,4 5,5 5,6 5,7
6,1 6,2 6,3 6,4 6,5 6,6 6,7

Cell [1,1] is selected by using either of the following selectors:

tr:first-child td:first-child

tr:first-child > :first-child 

:first-child > td:first-child 

Any of the following selectors will match cell [2,2]:

tr:first-child+tr td:first-child+td

tr:first-child+tr > :first-child+td

tr:first-child+tr :first-child+td

Either of the following on the other hand will match cell [6,7]:

tr:first-child+tr+tr+tr+tr+tr td:first-child+td+td+td+td+td+td

tr+tr+tr+tr+tr+tr > td+td+td+td+td+td+td

tr+tr+tr+tr+tr+tr td+td+td+td+td+td+td

Selecting an entire row is easy. The following example matches all the cells of row 4:

tr:first-child+tr+tr+tr td

If we want to match only a certain range of cells in that row, say cells [4,2] to [4,6] we can use the following selector:

tr:first-child+tr+tr+tr td+td

To match all the cells of column 5:

tr td:first-child+td+td+td+td