Best html questions in October 2011

JavaScript in <head> or just before </body>?

18 votes

I am about to embark on a new web project and I plan to put my JS-scripts in the head and before end-body using the following scheme:

  1. Scripts that are essential for the UX of the page goes in the head. As I've picked up perusing the web - scripts in the head is loaded before the page loads, so it would make sense to put scripts that are essential to the user experience there.

  2. Scripts that are non-essential to the design and UX (Google Analytics scripts etc.) of the page goes before the </body>.

Is this a sensible approach?

Another approach would be to put all the scripts in the <head> and add defer attributes to the non-essential scripts - however I've read that older versions of FF doesn't pick up the defer attribute.

I think a lot of developers run javascript just before the </body> so that it is ran after all the elements have been rendered.

However, if you organise your code correctly, the position on the page doesn't matter.

For example, when using jQuery, you can ensure the code isn't ran until the page and its elements are fully rendered by doing the following:

$(document).ready(function(){
   //Code here
});

Then the script reference can be put in the head tag.

Why "select" options are hidden?

10 votes

I have a HTML select like this:

<select name="something">
    <option value="a">1</option>
    <option value="b">2</option>
    <option value="c">3</option>
</select>

and I've noticed that jquery interprets that options are hidden HTML tags. The problem comes when I have to remove real hidden tags like in this example:

<form action="#" id="f">
    <select name="something">
        <option value="a">1</option>
        <option value="b">2</option>
        <option value="c">3</option>
    </select>
    <p style="display:none">hello world</p>
    <any_tag style="display:none">some text</any_tag>
</form>

If I execute this:

$("#f :hidden").remove();

all options are removed. The question is why jquery removes options? and what is the most appropriate selector to remove only hidden tags? (well or not option tags)

Here is a test.

You could just add the functionality that should already be there :P

$("#f :hidden:not(option)").remove();

How do browsers resolve conflicting classes?

10 votes

I know it's possible to specify multiple classes on an element in HTML:

<div class='one two'>Text</div>

It seems like classes are accessible from Javascript as a single string.

What happens when the classes are specified with conflicting properties? For instance

div.one {
  background-color: red; 
  color: blue;
}
div.two {
  background-color: green;
}

Will the result depend on the order the classes are specified in? For instance could I reasonably expect the div above to appear with blue text and a green background, because the two class becomes evaluated second, overwriting the background-color property?

Read about specificity:

Short answer: if two selectors have the same specificity, the last one to be declared wins.

The essential difference among HTML tags?

10 votes

Says the <b> tag make texts bold, but if assigned with CSS "font-weight:normal;" then it's absolutely like a normal tag. In the other side, <i> tag can be styled to display the text inside like a <b> tag:

<i style="font-style:normal; font-weight:bold;">

Yeah, i'm talking about the interchangeability of HTML tags, so we can have less tag.

And 2 of the most famous tags turn to be "div" and "span" which are discussed in this SO Question : What is the difference between HTML tags DIV and SPAN?

I want to know what is the essence of the <div> tag that makes a span tag like this:

<span style="display:block;"></span>

can not be a replacement for div? By another respect, what's the deep reason behind make these code become "invalid" (X)HTML:

<span style="display: block"><p>Still wrong</p></span>

Thanks!


For the scenario, I'm building a so-called "HTML-CSS-Generator", which requires the deep knowledge on HTML tag. I want to filter the sets of all valid HTML tags to make a sets of "major tags". Then I'm asking for the interchangeability of the tags.


Update (the ultimate goal of this question)

I wonder if the defference was that the tag is natively "block-level" (like div,p) or "inline-level" (like span) ?

Is there any other kind of "native property" (that CSS or JS cannot change) like "block/inline-level" for the HTML Tags ?

Don't go checking on how things render or how they look (eventhough this is part of the HTML specification). HTML is all about meaning.

What do the tags <u>, <i>, <b> mean? Right, they mean nothing! They only define how things look. That's exactly the reason why they were removed from the specification in HTML5 (or actually deprecated).

Ofcourse, you can style a <div> as a <span>, hell you could style an <div> as an <input type="text">. But that's not what it's about, it's all about meaning.

According to the HTML spec, a <div> is a divider. It divides certain parts of a website, certain sections as an Header or a Content Box go inside a <div>.

A <span> is used to specify something that's inline. Like the following

<div class="Location">    
   Currently I'm living in <span class="Country">The Netherlands</span>
</div>

Don't compare HTML tags based on how they render. Also always choose the HTML tag that most closely resembles the data that's displayed, even if it renders completely different than what you want.


The diffrence is not about whether they are block or inline (eventhough that's an effect of it). The difference is the data they represent.

Possible to scroll caret into view inside a single HTML text field with JavaScript?

10 votes

Knowing the jQuery Caret plugin, I'm still seeing no way to do the following on a single line text box in HTML (i.e. the input:type=text control) with JavaScript:

  1. Programmatically inserting text into a text box
  2. Setting the caret to the end.
  3. Making the caret visible (i.e. scroll the text box content)

I know how to do 1. and 2., just for 3. I have found no way of doing it.

To illustrate it:

enter image description here

My question is:

Is there any way to reliable put the caret at the end of the text and scroll it into the view?

(I can think of simulating pressing the END key or something like that, but I'm unsure whether this would be the best option).

//hack to get cursor at end:

$(textboxselector).val($(textboxselector).val());

edit: should note focus first:

$(textboxselector).val(newtext);
$(textboxselector).focus();
$(textboxselector).val($(textboxselector).val());

Is it possible to use javascript to detect if a screen reader is running on a users machine?

9 votes

I want to detect whether a screen reader is running on a user's machine to avoid sound clashing with audio tag in html. If so please provide details on how this could be done.

You should probably not try to do anything special even if you could detect that a screenreader is running. Even if you get it right for one group of screenreader users, you may get it wrong for another group. It's best to concentrate on writing good clean HTML5 in the first place.

Note that note all screenreader users use text-to-speech; many use braille output. Additionally, other types of accessibility tools - such as content highlighters and voice input apps - use the same techniques and APIs (eg. DOM, MSAA) that screenreaders do, so any technique that "detects a screenreader" will likely detect these also - so you cannot assume that it means that the user is fully blind and using only speech.

As things currently stand, the audio tag is currently not universally accessible, different browsers have different levels of accessibility support - see http://html5accessibility.com/ and scroll down to audio for more details of current support. I've seen some pages that add HTML5-based controls plus javascript after the audio tag so they can provide their own UI to ensure that keyboard or screenreader users can play/stop the audio as needed. (Eventually, when browsers catch up, this should not be needed.)

As far as general accessibility goes, WCAG 2.0 (Web Content Accessibility Guidelines - http://www.w3.org/TR/WCAG/) recommends that any audio that plays automatically for more than 3 seconds should have an accessible means to pause or stop the audio. (I'd go even further and recommend against using any automatic audio - when using tabbed browsing, it's often impossible to determine which tab the audio is coming from.)

@font-face and wrong letter tracking/spacing

9 votes

I've encountered a problem using @font-face while building a website. The font's installed on my PC, I've downloaded it from fontsquirrel.com.

If I use the version that's installed in my PC (Journal), all is well as you can see from the following screenshot:

However, as soon as I switch to the @font-face version, the letters' tracking (expecially Ts) is different and looks broken:

Here's the code for the @font-face (font-face kit downloaded from font squirrel):

@font-face {
font-family: 'JournalRegular';
src: url('journal-webfont.eot');
src: url('journal-webfont.eot?#iefix') format('embedded-opentype'),
     url('journal-webfont.woff') format('woff'),
     url('journal-webfont.ttf') format('truetype'),
     url('journal-webfont.svg#JournalRegular') format('svg');
font-weight: normal;
font-style: normal;
}

And here's the item (a div) styling:

#assignment-text {
font-family: Journal, JournalRegular, serif;
font-size: 3em;
text-align: center;
width: 340px;
position: absolute;
top: 200px;
left: 320px;
color: #000;
}

Using Journal everything is fine on my PC. Forcing JournalRegular (by commenting Journal) breaks spacing. I am developing in local. Tested in: Windows 7 PC (with font installed): Firefox 7, Chrome, Opera, IE9. Macbook (without font installed): Firefox, Safari.

Is this a known issue? I've searched but I can't seem to find a solution.

I've had similar problems with fonts I converted on font-squirrel. One of those times, going back to the generator and playing on the expert options, notably "Remove Kerning" solved it.

What is the maximum depth of HTML documents in practice?

8 votes

I want to allow embedding of HTML but avoid DoS due to deeply nested HTML documents that crash some browsers. I'd like to be able to accommodate 99.9% of documents, but reject those that nest too deeply.

Two closely related question:

  1. What document depth limits are built into browsers? E.g. browser X fails to parse or does not build documents with depth > some limit.
  2. Are document depth statistics for documents available on the web? Is there a site with web statistics that explains that some percentage of real documents on the web have document depths less than some value.

Document depth is defined as 1 + the maximum number of parent traversals needed to reach the document root from any node in a document. For example, in

<html>                   <!-- 1 -->
  <body>                 <!-- 2 -->
    <div>                <!-- 3 -->
      <table>            <!-- 4 -->
        <tbody>          <!-- 5 -->
          <tr>           <!-- 6 -->
            <td>         <!-- 7 -->
              Foo        <!-- 8 -->

the maximum depth is 8 since the text node "Foo" has 8 ancestors. Ancestor here is interpreted non-strictly, i.e. ever node is its own ancestor and its own descendent.

Opera has some table nesting stats, which suggest that 99.99% of documents have a table nesting depth of less than 22, but that data does not contain whole document depth.

EDIT:

If people would like to criticize the HTML sanitization library instead of answering this question, please do. http://code.google.com/p/owasp-java-html-sanitizer/wiki/AttackReviewGroundRules explains how to find the code, where to find a testbed that lets you try out attacks, and how to report issues.

EDIT:

I asked Adam Barth, and he very kindly pointed me to webkit code that handles this.

Webkit, at least, enforces this limit. When a treebuilder is created it receives a tree limit that is configurable:

m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document), maximumDOMTreeDepth**(document)))

and it is tested by the block-nesting-cap test.

It may be worth asking coderesearch@google.com. Their study from 2005 (http://code.google.com/webstats/) doesn't cover your particular question. They sampled more than a billion documents though, and are interested in hearing about anything you feel is worth worth examining.

--[Update]--

Here's a crude script I wrote to test the browsers I have (putting the number of elements to nest into the query string):

var n = Number(window.location.search.substring(1));

var outboundHtml = '';
var inboundHtml = '';

for(var i = 0; i < n; i++)
{
    outboundHtml += '<div>' + (i + 1);
    inboundHtml += '</div>';
}

var testWindow = window.open();
testWindow.document.open();
testWindow.document.write(outboundHtml + inboundHtml);
testWindow.document.close();

And here are my findings (may be specific to my machine, Win XP, 3Gb Ram):

  • Chrome 9: 3218 nested elements will render, 3129 crashes tab. (Chrome 9 is old I know, the updater fails on my corporate LAN)
  • Safari 5: 3477 will render, 3478 browser closes completely.
  • IE8: 1000000+ will render (memory permitting), although performance degrades significantly when into high 4-figure numbers due to event bubbling when scrolling/moving the mouse/etc. Anything over 10000 appears to lock up, but I think is just taking a very long time, so is effective DoS.
  • Opera 11: Just limited by memory as far as I can tell, i.e. my script runs out of memory for 10000000. For large documents that do render though, there doesn't seem to be any performance degradation like in IE.
  • Firefox 3.6: ~1500000 will render but testing above this range resulted in the browser crashing with Mozilla Crash Reporter or just hanging, sometimes a number which worked would fail a subsequent time, but larger numbers ~1700000 would crash Firefox straight from a restart.

More on Chrome:

Changing the DIV to a SPAN resulted in Chrome being able to nest 9202 elements before crashing. So it's not the size of the HTML that is the reason (although SPAN elements may be more lightweight).

Nesting 2077 table cells (<table><tr><td>) worked (6231 elements), until you scrolled down to cell 445, then it crashed, so you can't nest 445 Table Cells (1335 elements).

Testing with files generated from the script (as opposed to writing to new windows) give slightly higher tolerances, but Chrome still crashed.

You can nest 1409 list items (<ul><li>) before it crashes, which is interesting because:

  • Firefox stops indenting list items after 99, a programmatic constraint maybe.
  • Opera's keeps indenting with glitches at 250, 376, 502, 628, 754, 880...

Setting a DOCTYPE is effective in IE8 (putting it into standards mode, i.e. var outboundHtml = '<!DOCTYPE html>';): It will not nest 792 list items (the tab crashes/closes) or 1593 DIVs. It made no difference in IE8 whether the test was generated from the script or loaded from a file.

So the nesting limit of a browser apparently depends on the type of HTML elements the attacker is injecting, and the layout engine. There could be some HTML considerably smaller than this. And we have a plain-HTML DoS for IE8, Chrome and Safari users with a considerably small payload.

It seems if you are going to allow users to post HTML that gets rendered on one of your pages, it is worth considering a limit on nested elements if there a generous size limit.

How can I set the hotspot to the center of a custom cursor?

8 votes

I'm using a custom cursor (png image) on a web page using cursor CSS attributes. I'd like to know if i can center the cursor position (like the cross-hair cursor in Windows) and not using the default top-left position.

One solution will be to hide the cursor and create a div with the custom cursor which will follow the cursor position but maybe someone has a better solution.

If your cursor is in .cur format (only .cur and .ani are supported in IE), then whichever program you use to create the .cur can set the hotspot in the header.

If you're using any other image type, CSS 3 allows the x and y values of the hotspot to be set:

#myEl { cursor: url(mycursor.png) <x> <y>; } 

Supported in:

  • Firefox 1.5+
  • Safari 3+
  • Chrome 1+

References

Proper way to generate html dynamically with jQuery

7 votes

I found some different and conflicting answers on this topic.

I am building an application which works mostly with html dynamically generated by jQuery, based on results acquired from underlying API in form of JSON data.

I was told by some of my collegues (personally), that the best way would be to do something like this:

var ul = $("<ul>").addClass("some-ul");
$.each(results, function(index) {
  ul.append($("<li>").html(this).attr("id", index));
});
$("body").append($("<div>").attr("id", "div-id").addClass("some-div").append(ul));

etc. The reason I was told it was that "updates the DOM directly instead of parsing html to achieve it".

However, I see lots of code like this (same example):

var toAppend = '<div class="some-div" id="div-id"><ul>';
$.each(results, function(index) {
  toAppend += '<li id="' + index + '">' + this + '</li>';
});
toAppend += '</ul></div>'

Which I personally consider as not as elegant - but is it better? I googled the issue for a couple of minutes and found this article. Basically, it is about increasing performance drastically by using string concatenation - my "second way".

The main issue of this article is that it has been released in 2009 and discussed jQuery version is 1.3. Today, the current release is version 1.6.4 which can behave quite differently. And this is the issue of most articles on the subject I have already found and I'm also somehow suspicious about their credibility.

That's why I have decided to post the question here and ask - which method of generating DOM is actually the proper one, based on performance?

IMPORTANT EDIT:

I have written a little benchmark to test which approach is better considering performance.

jsFiddle - concatenation version

jsFiddle - array join version

Code:

var text = "lorem ipsum";
var strings = $("#strings");
var objects = $("#objects");
var results = $("#results");

// string concatenation
var start = new Date().getTime();
var toAppend = ['<div class="div-class" id="div-id1"><ul class="ul-class" id="ul-id1">'];
for (var i = 1; i <= 20000; i++) {
    toAppend[i] = '<li class="li-class" id="li-id1-' + i + '">' + text + '</li>';
}
toAppend[i++] = '</ul></div>';
results.append(toAppend.join(""));
strings.html(new Date().getTime() - start);

// jquery objects
var start = new Date().getTime();
var ul = $("<ul>").attr("id", "ul-id2").addClass("ul-class");
for (var i = 0; i < 20000; i++) {
    ul.append($("<li>").attr("id", "li-id2-" + i).addClass("li-class"));
}
results.append($("<div>").attr("id", "div-id2").addClass("div-class").append(ul));
objects.html(new Date().getTime() - start);

It seems that operating on strings is faster (in Firefox 7 about 7 times) than using jQuery objects and methods. But I can be wrong, especially if there are any mistakes or performance-decreasing bugs in this "benchmark's" code. Feel free to make any changes.

Note: I used Array join because of the article mentioned earlier instead of actual concatenation.

EDIT: Based on suggestion by @hradac, I used actual string concatenation in the benchmark and it did in fact improve the times.

First of all, this kind of micro-benchmarking almost never tells you what you want to really know. Second of all, your benchmarks are varied and not equivalent. For example, your first example generates lines that look like this:

<li class="li-class" id="li-id1-493">lorem ipsum</li>

and your second lines like this:

<li id="li-id2-0" class="li-class"></li>

Notice the different element order and the lack of "lorem ipsum" text. Nor is there any attempt to clean out the results div between tests to avoid performance issues as a result of the first 20K results already being there.

But beyond these issues is the question, "Is performance on this really disrupting the client side user experience?" Seriously? You're rendering such a quantity of text this way that you're seeing noticeable differences between the alternative methods rendering the text?

I'll harken back to what others have said, use a templating engine. The fastest ones are quite quick indeed and even have pre-compilation options to allow you to re-render the same template and get quick results. So don't believe me. Instead, believe a demonstration. Here's my jsFiddle to demonstrate the performance of the new JsRender library that is supposed to replace the jQuery Template engine...

http://jsfiddle.net/LZLWM/10/

Note: It can take several seconds for JsRender to load into the Fiddle. It's because I'm pulling it straight out of GitHub and that's not something that GitHub is particularly good at. I don't recommend that in actual practice. It doesn't change the timings though and it's necessary until jsFiddle starts incorporating templating engines as options.

Notice that the second example, much closer to a real-world example generates 20,000 lines using JSON as its starting point in time approximately the same as your fastest test (< 50ms difference on my machine). Note also that both the code and the template are much clearer and easier to work with than any mess of appends and string concatenation is ever going to be. How many iterations am I going to need to get my template right vs. what you're doing?

Use something simple and stop wasting time on this level of micro optimization when it's probably not even necessary. Instead use templates like this (or any of several other good templating engines) and make sure that you've got expires headers turned on, you're using a CDN, you've got gzip compression turned on on your server, etc. All the stuff that YSlow is telling you to do, because that will completely swamp the effects of what you're looking at here.

How can I understand this checkbox behaviour?

7 votes

Here is my HTML:

<input class='user_roles' id="chk" type=checkbox />
<input id="btn_on" type="button" value="on" />
<input id="btn_off" type="button" value="off" />

And my jQuery:

$('#chk').click(function() {
    if($(this).prop("checked") === true) {
        alert ("checked");   
    }
    else{
        alert ("not checked");
    } 
});

$("[id$=btn_on]").click(function () {
    $('#chk').click();
});

$("[id$=btn_off]").click(function () {
    $('#chk').click();
});

A working example is here.

When the checkbox is clicked with the mouse it is checked straight away - that is, the alert displays "checked". However when one of the buttons is clicked, which indirectly call the click method on the checkbox, the checkbox is not clicked until after the click code has been run.

To test this, click the check box a couple of times with the mouse and you will see the alerts "checked" and "not checked" respectively. Click "On" and you will see the alert "not checked", and then the checkbox becomes checked. If you then click "Off" you will see "checked" followed by the checkbox unchecking itself.

What is the reason for this behaviour? How can I ensure that the checkbox "checking" happens before the click listener code is called, as per the mouse behaviour?

if its just a question about getting it to work, use .change() instead of .click() on your check box, if its about why it does what it does i have no idea sorry

Why the font size won't change with browser zoom in?

7 votes

In most of websites, while I change the zoom level of browsers, the font size will also increase and help user to see them. For some reasons, that just won't work on my new website. While I change the zoom level of the browser, everything changes but all font size keep the same. Is there a css or html property that I can use to control this behavior? Thanks

here is an example: http://ca.skywatcher.com/index.php

The problem is that you have set -webkit-text-size-adjust: none; for the body in layout.css. Changing it to -webkit-text-size-adjust: auto; allows the zooming of the fonts along with the page.

I guess this is just one weird speciality of Chrome (at least for me it was zooming correctly in Firefox).

Edit: Corrected the CSS. Should be auto not 0

writing right-to-left sentences in ASP.NET labels and text boxes

7 votes

how can I CORRECTLY display English and non-English (Persian, Farsi language, middle eastern) words in ASP.NET labels or text boxes? it is OK when I type or display only English or only non-English (Farsi) words, but when I type or display a sentence which contains both of them, everything gets out of order, my sentences are misplaced, punctuation symbols are wrongly inserted, in another word it is difficult to understand what is written. When I'm going to use Office Word for writing Persian documents (which may contain English words), first I set paragraph direction as Right-To-Left, is it possible to do something similar in ASP.NET? of course I set following style in my ASPX files and now my texts boxes start writing from right to left but it does nothing for solving the aforementioned problem!

Style="text-align: right"

how can I solve it? thanks

You need to use the correct value for the dir attribute - in this case, rtl:

dir="rtl"

This needs to be done in the containing element.

There are also CSS properties you can set, as discussed in this document (thanks @ANeves).

How to check if a DOM Node is the node representing the doctype declaration?

7 votes

So let's say (in IE8) that we have a document.

Now normally we can assume that document.childNodes[0] is the doctype. So

var doctype = document.childNodes[0]

Now how do we confirm rather then assume it is the doctype?

doctype.nodeType === Node.COMMENT_NODE;
doctype.tagName === "!"; // same as a comment
doctype.data.indexOf("DOCTYPE ") > -1; // same as any comment containing the word DOCTYPE.
doctype === document.doctype; // false, document.doctype is undefined in IE8

Apart from assumptions, how am I supposed to know whether a given node is a doctype?

For those of you unfamiliar with DOM4 take a look at DocumentType

The DOM-shim get's document.doctype in IE8 by just returning document.childNodes[0]

IE8 says no. :(

Seriously though, apart from hacks and assumptions there is no clean way.

As suggested in the comments you can assume comments are not doctype like

doctype.data.indexOf("<!DOCTYPE html") !== -1 && doctype.data.indexOf(">") !== -1

Or make assumptions about the DOM structure

I believe that only comment nodes, (and anything treated by the parser as a comment node, e.g. an xml declaration) can precede the doctype

So you can just loop over the comment nodes in document.childNodes until you find one that matches the above regexp.