HTML & XHTML

From Elvanör's Technical Wiki
Revision as of 21:10, 10 March 2008 by Elvanor (talk | contribs)
Jump to navigation Jump to search

Various important things I noticed when writing HTML & CSS code.

HTML

Elements

  • <span> elements are like DIVs, but inline.
  • <textarea> elements are not blick elements, they behave like inline elements. Actually they are inline-block elements, which means that their content is treated like a block, but the element itself is treated like an inline element.
  • <div> elements are not permitted inside a <p> element; it is DIV elements that should englobe other elements, not the contrary.
  • As much as possible, use elements like <strong>, <em>, <cite>, <h1>... Do not try to define styles that will render as these elements. Not only doing this adds better structure to the document, thus helping others to understand it, but it also helps for search engines (hopefully).

Embedding style sheets, JavaScript in HTML documents

  • Not too sure about that, but it seems you can use a <link> tag only in the <head> section of the document.
  • Do not use <link> for JavaScript code. You must use <script src="code.js" > </script> syntax. Avoid closing the <script> tag in the same element (eg, <script />); it won't work, and will completely confuse the browser! It is maybe possible to use <link> for JS code but then the <script> tag must appear in the file (untested).

Forms

  • If you use the GET method on a form, on the action URL, don't give an URL already containing variables encoded in GET style. The browser will just rebuild the URL when you submit the form, and thus the variables will be ignored. Eg, something like:
<form action="myurl.html?myVariable=yes&myCounter=3" method="GET"><button type="submit></button></form>

won't work. If you want to pass variables and use a GET method, just create hidden input fields.

  • If you want to provide a styled submit button (an image, or even more complex CSS), use the button element, not the input (with type=submit) element. To remove the actual button in a cross-browser way, you should:
    • Set background-color: transparent; border: 0px.
    • Set the height and width of the button to the dimensions of the images (height should actually be one pixel more, for Firefox).

Tables

  • <div> elements are not permitted, only and .
  • The <tbody> tag is not mandatory, but the element is. This means a tbody element will be created in the DOM even if you don't specify the tags in your HTML source. Be aware of this as it can lead to subtle errors if you manipulate the DOM later.
  • You usually want the HTML attributes cellspacing and cellpadding set to 0 on your tables.

Inner Frames (iframes)

  • DISCLAIMER: iframes are bad; do not use them if you can avoid that.
  • POSTing to an iframe from the outside is possible, see the code below:
  <iframe src='form_handler.php' frameborder="0"  name="reference_tag" />

  <form method='post' action='form_handler.php' target='reference_tag'>
      <input type='text' value='Random text'>
      <input type='submit'>
  </form>

Note that the src attribute on the iframe is not mandatory with this technique.

  • You can use an inner frame to "erase" Flash content. This is especially useful on Linux; it allows you to erase parts of a Flash to redraw dynamic HTML over it (the Flash player has a bug on Linux that normally prevents HTML content to be drawn over a Flash object). An useful link.

XHTML 1.0 & 1.1

  • Don't use the name attribute on forms, a, img or map elements. Only use id.
  • XHTML documents should be served with the MIME type "application/xhtml+xml" and NOT "text/html". If served properly as XML documents, this will cause Firefox to parse them using the XML parser, not the TagSoup parser. When served as text/html, the TagSoup parser will be used even if the document type is declared as XHTML.
  • However, currently there are lots of problems associated with XML documents. In particular, the JavaScript code document.write() does not work. This leads Script.aculo.us (for example) to fail. So actually it is almost impossible to use XML parsing.
  • Also note that IE 7 does not support "application/xhtml+xml" at all.
  • An empty self-closing div (
    ) is perfectly legal in XHTML. However, it will cause problems if parsed by Firefox HTML parser, so you must not use it. Always close your divs with a
    .

XHTML Strict

  • The iframe tag is not legal, as well as the target attribute in a link or form. This makes the use of Ajax upload almost impossible to achieve in an XHTML Strict compliant way.

Validation

  • When using Firefox, be very careful of the difference between "generated source" or "simple source". The generated source is produced by Firefox, and so contains the changes brought by DHTML, Ajax etc. However, this also means that this is the source once it is reinterpreted by Firefox which may add elements or remove some...
  • Even if you save the page, it will save the source reinterpreted by Firefox. Almost the only way to obtain the source as first sent by the server is to view the source and then save it in Firefox. This of course precludes any DHTML changes.
  • So the real solution is to install a special Firefox extension for validation. TotalValidator seems a good one.

CSS

Selectors

To apply an "AND" on a selector in CSS (for example, to apply a style to elements belonging to two classes), just repeat the normal selector, like this:

*.first_class.second_class

This would probably also work on class and ID, etc (untested yet):

*.first_class#my_id

To select every column in a table except the first one, use the following selector:

tr td + td

To eliminate the first row from the selector, just add tr +:

tr + tr td + td
  • There is no negative selector in CSS 2.1 (for example, select elements that don't have this class name). There is one in CSS 3.

Rules

  • Rules do not apply in the order they are encountered, but in the order of their specificity. For example if you have a rule with a selector of p and a rule with a selector of p.Class, the later will be favored even if it is encountered earlier in the CSS file. This makes sense.

Display

  • Note that display: inline; does not restrict the width whatsoever. This means that if you have a <div> element with display: inline, and a child that creates a block element like <p>, the child element will take all the place available. This will actually nullify the effect of the parent display: inline property.
  • Don't use an element that has display: inline property if it contains block children.
  • display: inline-block; is currently NOT supported on Firefox (although support is already implemented in CVS as of May 2007), and only partially supported in IE. This means: do not use it.

Positioning

  • Do not, ever, put a position: relative on your body element. This causes all sort of display problems with Firefox, and probably other browsers as well. It also confuses Prototype to the point that some functions such as cumulativeOffset() don't work anymore.

Absolute Positioning

  • This is done with respect to the parent element/block (the container). Thus, if you have a containing block, and inside a div with absolute positioning and bottom: 0px; it will get drawn at the bottom of the containing block. The parent block needs to have its positioning set as relative, fixed or absolute.

Floats

  • Floats don't work with absolutely or relatively positioned elements, only with those elements in the normal flow.
  • A div that is positioned to the right of a left floating block still takes the whole width that it is allowed to take. It is only its content that is positioned next to the floating block. This makes it impossible to use properties such as padding-left, they won't apply as expected. You can use a span instead of a div, or position the block as relative and use left: 25px instead of padding: 25px.
  • An element positioned next to a float still seems to have its top-left coordinate equal to the top-left coordinate of the floating element (this seems strange)! Note that this can cause problems with absolute positioned elements inside such a container (I am speaking of a container next to a float).
  • An inline element next to a float still "breaks" the flow. For example if you have a left floating div followed by an image, then a div, the last div won't float. It will be placed below the first div.

Margins and Paddings

  • The difference between margins and paddings is that margins don't get the element's background color or image. Margins are just transparent. Padding on the other hand get the background color/image.
  • Margins can also collapse. See this W3C reference. The idea is that adjoining elements margins can join together. This can happen especially happen with empty elements and cause troubles. I am not sure of the best way to prevent margins from collapsing. One way seems to set overflow: hidden, another is probably to apply a clearer div (a div with clearance).

Tables

  • Margins don't seem to work at all with table elements (it would work with the table itself, though). Paddings seem to work only with elements, not .
  • So the recommended way to specify spacings between elements in a table is through the specific 'border-spacing' property. Note that this property should be applied to the table element, not the <td>.
  • Note that the border property, specifying the border of the cell, should be on the contrary applied to each cell, like this:
table.WithBorders td {border: 1px solid black; padding: 3px;}

If you write this, borders will have in fact most of the time 2 pixels, because the borders will not be merged between two cells. If you want them to merge (and thus always have only 1 pixel), use border-collapse: collapse; in your table element.

  • You can specify certain properties to be applied to an entire column in a table (for example the 'border' property). However not all properties can be such applied, apparently. For example, I don't know how to apply the text-align property to an entire column (or if it is even possible). Usually it should just be applied to all the tds with a certain CSS class name.
  • To set the width of a column in CSS, the best is to use the <th> element, like this:
th.QuantityHeader {
	width: 75px;
	text-align: center;
}

Note that the text-align will only work for the cell, not the column; but the width will apply to the whole column.

Widths and Heights

  • If you have an empty div, setting a width won't make it appear on the page. You will also need to set the height.
  • Note that the height of a parent block level element is the sum of the height of its children, however floated elements are NOT taken into account. To force them to be taken into account, use a clearer div after the float element. This is a div that has clearance applied to it. Note that there may be other techniques to achieve the same result. See this link. Absolutely positioned elements are also taken out of the normal flow and thus don't contribute to the parent block height.
  • You can also explicitly set the height of the parent block.
  • By default, the width of a block level element is 100% of the available width (which is given by the containing block).

Empty Elements

  • Setting a height on an empty div will prevent Firefox from not inserting it into the DOM. This can be very useful.

Creating a box with custom borders (rounded corners)

  • There are a lot of ways to create rounded borders. Some use JavaScript, some use pure CSS (no images), some support transparencies, others not... Below is a list of interesting links (that support transparency and don't use JS):
  • Here are some of my methods. They are adapted from common methods.
    • Create a content div and 8 divs inside. Set the background-position accordingly for each of the divs. The last thing is to add a last div, the content div, and set the padding in that div equal to the widths/heights of the outer divs. This method does not support transparency, and uses overwriting, so this means you must be careful in the order of the 8 divs. This is not a recommended way.
    • Create 3 divs with position: relative (so that they start a parent block), each containing 3 divs. The left and right divs (for every one of the 3 rows) must be positioned absolutely, respectively to the left and right. The central div must have correct margins applied to it. The HTML code looks like:
    <div class="TopRow">
        <div class="TopLeftBorder"></div>
	<div class="TopBorder"></div>
	<div class="TopRightBorder"></div>
    </div>
		
    <div class="MiddleRow">
	<div class="LeftBorder"></div>
	<div class="RightBorder"></div>	
	<div class="InnerContent">
            Here some content.						
	</div>
    </div>
		
    <div class="BottomRow">
	<div class="BottomLeftBorder"></div>
	<div class="BottomBorder"></div>
	<div class="BottomRightBorder"></div>
    </div>

This is probably the best technique available. It forces you to have the three additional rows, which is bad, but it's the most versatile as it will adapt to varying heights and widths.

  • The newest technique I have found is just to have inside the main div, 9 other divs. The 8 outer ones will be absolutely positioned with negative offsets corresponding to their width / height. This method is slightly better than the previous one as it does not need the three additional row divs, and allows you to place the outer divs where you want. It is recommended to place them before the central div, as it will allow to use some Prototype DOM walking functions without problems. Note that the inconvenient of this method when compared to the previous one is that it forces you to calculate the width of the top and bottom divs, and the height of the left and right divs. This method is recommended when you can draw outside the decorated block, as it is intended to overflow.

Vertical Centering

  • See here for a good article.
  • Basically the following code will work. It does require you to know the height of the block you want to center (another technique allows you to center without assigning a height to the element, but is more complex):
<div style="position: relative; height: 200px;">
    <div style="position: absolute; top: 50%; margin-top: -50px; height: 100px;">
	Hello World!
    </div>
</div>

Horizontal Alignment

  • There are basically two methods to align to the right for example. The first is to use an absolutely positioned element with a right: 0px CSS property. The second is to float the element to the right. WARNING: There seems to be a bug with Firefox. If you float to the right a div that has a width, inside an absolutely positioned element, this element won't count towards the computing of the parent absolutely positioned element. Thus the parent div will likely take all available space. To workaround this, give a width directly on the parent element.

Horizontal Centering

  • text-align: center will only work with inline elements. For block level elements you must specify a width on them and use the margin properties (margin: auto).

Forms

  • To get all form elements correctly aligned, the best is to set the width of the labels to an equal value (and to set them as floats, so this width actually applies).
  • Unfortunately, a div element floating next to input fields can mask access to these fields (making impossible to click on the field to select it). One work around is to use a span or restrict the width of the div.

Inline elements

  • You cannot force an inline element to have a given width. One workaround is to float this element.

Techniques

  • To get a container block with two divs inside, one to the left and the other to the right, you can just float left the inside div and use text-align: right on the one who needs to go to the right.