" > some.html
45 |
46 |
47 | We use **heredocs** to make it easier to work with multi-line strings. So you'll want to be comfortable with this notation, using **cat**, to add a heredoc to a file (though we'll practice more of it in another lesson):
48 |
49 | # To send a string to a new file, using cat and heredocs
50 | cat > some.html <<'EOF'
51 |
52 |
53 |
Hello there
54 | Hey mom, I'm using "quotes"!
55 | EOF
56 |
57 |
58 | To _append_ to a file, you should already be familiar with `>>`:
59 |
60 | # To append a string using cat and heredocs
61 | cat >> some.html <<'EOF'
62 |
Here's another paragraph for you
63 | EOF
64 |
65 |
66 | # Seeing your own web pages
67 |
68 | If you're on **corn.stanford.edu**, think about working in your `~/WWW` directory, as all pages and files saved there can be accessible to the web.
69 |
70 | For example, in the code snippet below, I'm creating a page at: `~/WWW/playground/hello.html`:
71 |
72 | mkdir -p ~/WWW/playground
73 | cat > ~/WWW/playground/hello.html <<'EOF'
74 |
75 |
76 | This is Dan's page
77 |
78 |
79 |
80 |
85 |
86 | EOF
87 |
88 | # And let's add a little more, notice the use of double
89 | # right-braces to append to the file
90 |
91 | cat >> ~/WWW/playground/hello.html <<'EOF'
92 |
And here's Bill Murray
93 |
94 | EOF
95 |
96 |
97 | My **SUnet ID** is `dun`, which means `~/WWW/playground/hello.html` will be viewable at:
98 |
99 | [http://stanford.edu/~dun/playground/hello.html](http://stanford.edu/~dun/playground/hello.html)
100 |
101 | About HTML
102 | ----------
103 |
104 | ### The HTML Element
105 |
106 | The structural building block of HTML is the [HTML Element](http://en.wikipedia.org/wiki/HTML_element)
107 |
108 | Below is an example of a **paragraph** element:
109 |
110 |
111 | "They’ll keep out of my way," she insisted. "It takes two to make an accident."
112 |
113 |
114 |
115 | The textual content in the paragraph element is enclosed a **start tag**, `
`, and its corresponding **end tag**, `
` – note the end tag's _forward-slash_ that makes the difference between it and the start tag.
116 |
117 | ### Let's make a webpage
118 |
119 | And that's about all we need to know to make a _functional_ (though egregiously non-standard) web page. If you're on **corn.stanford.edu**, change into your personal (but not _private_) `~/WWW` directory and create a subdirectory for trying things out:
120 |
121 | mkdir -p ~/WWW/webtest
122 | cd ~/WWW/webtest
123 | # Make a webpage named `foo.html` consisting of a single paragraph element:
124 | cat > foo.html <<'EOF'
125 |
126 | "They'll keep out of my way," she insisted. "It takes two to make an accident."
127 |
128 | EOF
129 |
130 |
131 | **Note:** Above, [I use what's called a "heredoc"](http://stackoverflow.com/questions/2953081/how-can-i-write-a-here-doc-to-a-file-in-bash-script) to quickly dump a line into a new file. If you find its syntax weird, then just use **nano** to create the new file.
132 |
133 | If you visit http://www.stanford.edu/~your\_sunet\_id/webtest/foo.html, you should see something like this:
134 |
135 | 
136 |
137 | That's not very impressive, so add a couple of other paragraph elements (and some arbitrary whitespace). Again, use **nano** to copy-and-paste if you don't like the look of that `EOF`:
138 |
139 | cat >> foo.html <<'EOF'
140 |
141 | "Suppose you met somebody just as careless as yourself."
142 |
143 |
144 |
145 | "I hope I never will," she answered. "I hate careless people. That's why I like you."
146 |
147 | EOF
148 |
149 |
150 | The result:
151 |
152 | 
153 |
154 | ### Insignificant whitespace
155 |
156 | One thing that should be apparent is that the _amount of whitespace_, both between the elements and within the tags of the elements, makes not a bit of difference in the _physical_ layout of the webpage, as rendered by the browser.
157 |
158 | Let's confirm that, via the command-line. Execute a command that removes **newline** characters from `foo.html` and redirect it into a new file: `foo-oneline.html`
159 |
160 | cat foo.html | tr -d '\n' > foo-oneline.html
161 |
162 |
163 | Visit the `foo-oneline.html` in your browser. You should see no change to the physical appearance of the text.
164 |
165 | HTML is said to be a **whitespace insignificant** language. In terms of the _content_, whitespace doesn't make a difference – all consecutive spaces and newlines are treated as a single space. This is mostly trivia to us, but in pragmatic terms, this means we can space HTML elements as much (or as little) as we need to, without disrupting what is shown in the browser.
166 |
167 | ### Tags as structure
168 |
169 | Now instead of removing whitespace, let's remove the **tags** of the elements, and save the result as a new file, `foo-no-p.html`. We can do this in two ways; using the **pup** HTML parser:
170 |
171 | cat foo.html | pup 'text{}' > foo-no-p.html
172 |
173 |
174 | – or via good 'ol **sed** and its **substitution** function:
175 |
176 | cat foo.html | sed -E 's#?p>##g' > foo-no-p.html
177 |
178 |
179 | Now visit `foo-no-p.html`:
180 |
181 | 
182 |
183 | Looks like the `
` tags made all the difference. By default, web browsers treat `
` elements as _blocks_ – each block element occupies an entire "line" of the browser window. With the `
` tags removed, no such blocks exist, and thus, no line-by-line separation.
184 |
185 | **Note:** The block nature of the paragraph (i.e. `
`) element is the default, but ultimately, that characteristic, as well as the _physical appearance_ of paragraphs, and _every other element of a webpage_, is completely mutable, as we'll see when we get to the topic of [Cascading Style Sheets](#css)
186 |
187 | ### Nesting HTML elements
188 |
189 | One characteristic of HTML is the ability to nest elements within each other. For example, if we wanted to _emphasize_ a sentence in a paragraph, we would wrap that sentence in `` tags:
190 |
191 | cat foo.html | sed -E 's#(I hate careless people)#\1#'
192 |
193 |
194 | (Note the usage of [capturing groups](http://www.thegeekstuff.com/2009/10/unix-sed-tutorial-advanced-sed-substitution-examples/): one of the best features of regular expressions)
195 |
196 | The result:
197 |
198 |
199 | "They'll keep out of my way," she insisted. "It takes two to make an accident."
200 |
201 |
202 | "Suppose you met somebody just as careless as yourself."
203 |
204 |
205 |
206 |
207 |
208 | "I hope I never will," she answered. "I hate careless people. That's why I like you."
209 |
210 |
211 |
212 | And the result, if we pipe it into a new page named `foo-em.html` – notice the italicized text:
213 |
214 | 
215 |
216 | There's not much to note here, except that you want your nested start and end tags to be self-contained within their **parent\_\_element. The `
` element is considered to be the \_\_parent** of the `` element:
217 |
218 |
219 | "I hope I never will," she answered. "I hate careless people. That's why I like you."
220 |
221 |
222 |
223 | This is **bad** form, having the child element's closing tag _after_ its parent's closing tag:
224 |
225 |
226 | "I hope I never will," she answered. "I hate careless people. That's why I like you."
227 |
291 |
292 |
293 | Here's some more boilerplate, the `` element is used to enclose meta information and links to external files and code, which we'll cover later, and the `` tag wraps around all the actual content of the page:
294 |
295 |
296 |
297 | My page
298 |
299 |
300 |
307 |
308 |
309 |
310 | Try outputting these two files to your "~/WWW" directory, one with some boilerplate and the other with more boilerplate, and then visiting them in your browser:
311 |
312 | This page will live at `www.stanford.edu/~yourname/test/simple.html`
313 |
314 | mkdir -p ~/WWW/test/
315 | cat > ~/WWW/test/simple.html <<'EOF'
316 |
317 | My page
318 |
317 | > ```
318 |
319 | This markup would be translated to the following DOM tree:
320 |
321 | 
322 |
323 | **Figure : DOM tree of the example markup**
324 |
325 | Like HTML, DOM is specified by the W3C organization. See [www.w3.org/DOM/DOMTR](http://www.w3.org/DOM/DOMTR). It is a generic specification for manipulating documents. A specific module describes HTML specific elements. The HTML definitions can be found here: [www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.html](http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.html).
326 |
327 | When I say the tree contains DOM nodes, I mean the tree is constructed of elements that implement one of the DOM interfaces. Browsers use concrete implementations that have other attributes used by the browser internally.
328 |
329 | #### The parsing algorithm
330 |
331 | As we saw in the previous sections, HTML cannot be parsed using the regular top down or bottom up parsers.
332 |
333 | The reasons are:
334 |
335 | 1. The forgiving nature of the language.
336 | 2. The fact that browsers have traditional error tolerance to support well known cases of invalid HTML.
337 | 3. The parsing process is reentrant. For other languages, the source doesn't change during parsing, but in HTML, dynamic code (such as script elements containing `document.write()` calls) can add extra tokens, so the parsing process actually modifies the input.
338 |
339 | Unable to use the regular parsing techniques, browsers create custom parsers for parsing HTML.
340 |
341 | The [parsing algorithm is described in detail by the HTML5 specification](http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html). The algorithm consists of two stages: tokenization and tree construction.
342 |
343 | Tokenization is the lexical analysis, parsing the input into tokens. Among HTML tokens are start tags, end tags, attribute names and attribute values.
344 |
345 | The tokenizer recognizes the token, gives it to the tree constructor, and consumes the next character for recognizing the next token, and so on until the end of the input.
346 |
347 | 
348 |
349 | **Figure : HTML parsing flow (taken from HTML5 spec)**
350 |
351 | ### The tokenization algorithm
352 |
353 | The algorithm's output is an HTML token. The algorithm is expressed as a state machine. Each state consumes one or more characters of the input stream and updates the next state according to those characters. The decision is influenced by the current tokenization state and by the tree construction state. This means the same consumed character will yield different results for the correct next state, depending on the current state. The algorithm is too complex to describe fully, so let's see a simple example that will help us understand the principle.
354 |
355 | Basic example--tokenizing the following HTML:
356 |
357 | > ```lang-html
358 | > Hello world
359 | > ```
360 |
361 | The initial state is the "Data state". When the `<` character is encountered, the state is changed to **"Tag open state"**. Consuming an `a-z` character causes creation of a "Start tag token", the state is changed to **"Tag name state"**. We stay in this state until the `>` character is consumed. Each character is appended to the new token name. In our case the created token is an `html` token.
362 |
363 | When the `>` tag is reached, the current token is emitted and the state changes back to the **"Data state"**. The `` tag will be treated by the same steps. So far the `html` and `body` tags were emitted. We are now back at the **"Data state"**. Consuming the `H` character of `Hello world` will cause creation and emitting of a character token, this goes on until the `<` of `` is reached. We will emit a character token for each character of `Hello world`.
364 |
365 | We are now back at the **"Tag open state"**. Consuming the next input `/` will cause creation of an `end tag token` and a move to the **"Tag name state"**. Again we stay in this state until we reach `>`.Then the new tag token will be emitted and we go back to the **"Data state"**. The `` input will be treated like the previous case.
366 |
367 | 
368 |
369 | **Figure : Tokenizing the example input**
370 |
371 | #### Tree construction algorithm
372 |
373 | When the parser is created the Document object is created. During the tree construction stage the DOM tree with the Document in its root will be modified and elements will be added to it. Each node emitted by the tokenizer will be processed by the tree constructor. For each token the specification defines which DOM element is relevant to it and will be created for this token. The element is added to the DOM tree, and also the stack of open elements. This stack is used to correct nesting mismatches and unclosed tags. The algorithm is also described as a state machine. The states are called "insertion modes".
374 |
375 | Let's see the tree construction process for the example input:
376 |
377 | > ```lang-html
378 | > Hello world
379 | > ```
380 |
381 | The input to the tree construction stage is a sequence of tokens from the tokenization stage. The first mode is the **"initial mode"**. Receiving the "html" token will cause a move to the **"before html"** mode and a reprocessing of the token in that mode. This will cause creation of the HTMLHtmlElement element, which will be appended to the root Document object.
382 |
383 | The state will be changed to **"before head"**. The "body" token is then received. An HTMLHeadElement will be created implicitly although we don't have a "head" token and it will be added to the tree.
384 |
385 | We now move to the **"in head"** mode and then to **"after head"**. The body token is reprocessed, an HTMLBodyElement is created and inserted and the mode is transferred to **"in body"**.
386 |
387 | The character tokens of the "Hello world" string are now received. The first one will cause creation and insertion of a "Text" node and the other characters will be appended to that node.
388 |
389 | The receiving of the body end token will cause a transfer to **"after body"** mode. We will now receive the html end tag which will move us to **"after after body"** mode. Receiving the end of file token will end the parsing.
390 |
391 | 
392 |
393 | **Figure : tree construction of example html**
394 |
395 | ### Actions when the parsing is finished
396 |
397 | At this stage the browser will mark the document as interactive and start parsing scripts that are in "deferred" mode: those that should be executed after the document is parsed. The document state will be then set to "complete" and a "load" event will be fired.
398 |
399 | You can see [the full algorithms for tokenization and tree construction in the HTML5 specification](http://www.w3.org/TR/html5/syntax.html#html-parser)
400 |
401 | ### Browsers' error tolerance
402 |
403 | You never get an "Invalid Syntax" error on an HTML page. Browsers fix any invalid content and go on.
404 |
405 | Take this HTML for example:
406 |
407 | > ```lang-html
408 | >
Really lousy HTML
409 | > ```
410 |
411 | I must have violated about a million rules ("mytag" is not a standard tag, wrong nesting of the "p" and "div" elements and more) but the browser still shows it correctly and doesn't complain. So a lot of the parser code is fixing the HTML author mistakes.
412 |
413 | Error handling is quite consistent in browsers, but amazingly enough it hasn't been part of HTML specifications. Like bookmarking and back/forward buttons it's just something that developed in browsers over the years. There are known invalid HTML constructs repeated on many sites, and the browsers try to fix them in a way conformant with other browsers.
414 |
415 | The HTML5 specification does define some of these requirements. (WebKit summarizes this nicely in the comment at the beginning of the HTML parser class.)
416 |
417 | > The parser parses tokenized input into the document, building up the document tree. If the document is well-formed, parsing it is straightforward.
418 | >
419 | > Unfortunately, we have to handle many HTML documents that are not well-formed, so the parser has to be tolerant about errors.
420 | >
421 | > We have to take care of at least the following error conditions:
422 | >
423 | > 1. The element being added is explicitly forbidden inside some outer tag. In this case we should close all tags up to the one which forbids the element, and add it afterwards.
424 | > 2. We are not allowed to add the element directly. It could be that the person writing the document forgot some tag in between (or that the tag in between is optional). This could be the case with the following tags: HTML HEAD BODY TBODY TR TD LI (did I forget any?).
425 | > 3. We want to add a block element inside an inline element. Close all inline elements up to the next higher block element.
426 | > 4. If this doesn't help, close elements until we are allowed to add the element--or ignore the tag.
427 |
428 | Let's see some WebKit error tolerance examples:
429 |
430 | ` instead of `
431 |
432 | `Some sites use instead of . In order to be compatible with IE and Firefox, WebKit treats this like .\`
433 |
434 | The code:
435 |
436 | > ```lang-html
437 | > if (t->isCloseTag(brTag) && m-document->inCompatMode()) {
438 | > reportError(MalformedBRError); t->beginTag = true;
439 | > }
440 | > ```
441 |
442 | Note that the error handling is internal: it won't be presented to the user.
443 |
444 | #### A stray table
445 |
446 | A stray table is a table inside another table, but not inside a table cell.
447 |
448 | For example:
449 |
450 | > ```lang-html
451 | >
inner table
outer table
452 | > ```
453 |
454 | WebKit will change the hierarchy to two sibling tables:
455 |
456 | > ```lang-html
457 | >
outer table
inner table
458 | > ```
459 |
460 | The code:
461 |
462 | > ```lang-html
463 | > if (m-inStrayTableContent && localName == tableTag)
464 | > popBlock(tableTag);
465 | > ```
466 |
467 | WebKit uses a stack for the current element contents: it will pop the inner table out of the outer table stack. The tables will now be siblings.
468 |
469 | #### Nested form elements
470 |
471 | In case the user puts a form inside another form, the second form is ignored.\
472 | The code:
473 |
474 | > ```lang-html
475 | > if (!m-currentFormElement) {
476 | > m-currentFormElement = new HTMLFormElement(formTag,
477 | > m-document); }
478 | > ```
479 |
480 | #### A too deep tag hierarchy
481 |
482 | The comment speaks for itself.
483 |
484 | > www.liceo.edu.mx is an example of a site that achieves a level of nesting of about 1500 tags, all from a bunch of ``s. We will only allow at most 20 nested tags of the same type before just ignoring them all together.
485 |
486 | > ```lang-html
487 | > bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
488 | > {
489 | > unsigned i = 0;
490 | > for (HTMLStackElem\* curr = m-blockStack;
491 | > i < cMaxRedundantTagDepth && curr && curr->tagName ==
492 | > tagName;
493 | > curr = curr->next, i++) { }
494 | > return i != cMaxRedundantTagDepth;
495 | > }
496 | > ```
497 |
498 | #### Misplaced html or body end tags
499 |
500 | Again--the comment speaks for itself.
501 |
502 | > Support for really broken HTML. We never close the body tag, since some stupid web pages close it before the actual end of the doc. Let's rely on the end() call to close things.
503 |
504 | > ```lang-html
505 | > if (t->tagName == htmlTag || t->tagName == bodyTag ) return;
506 | > ```
507 |
508 | So web authors beware--unless you want to appear as an example in a WebKit error tolerance code snippet--write well formed HTML.
509 |
510 | ## CSS parsing
511 |
512 | Remember the parsing concepts in the introduction? Well, unlike HTML, CSS is a context free grammar and can be parsed using the types of parsers described in the introduction. In fact [the CSS specification defines CSS lexical and syntax grammar](http://www.w3.org/TR/CSS2/grammar.html).
513 |
514 | Let's see some examples:\
515 | The lexical grammar (vocabulary) is defined by regular expressions for each token:
516 |
517 | > comment \/\*[^*]-\*+([^/-][^*]-\*+)-\/
518 | > num [0-9]+|[0-9]-"."[0-9]+
519 | > nonascii [\200-\377]
520 | > nmstart [-a-z]|{nonascii}|{escape}
521 | > nmchar [-a-z0-9-]|{nonascii}|{escape}
522 | > name {nmchar}+
523 | > ident {nmstart}{nmchar}-
524 |
525 | "ident" is short for identifier, like a class name. "name" is an element id (that is referred by "#" )
526 |
527 | The syntax grammar is described in BNF.
528 |
529 | > ```lang-bnf
530 | > ruleset
531 | > : selector [ ',' S* selector ]*
532 | > '{' S* declaration [ ';' S* declaration ]* '}' S*
533 | > ;
534 | > selector
535 | > : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]?
536 | > ;
537 | > simple_selector
538 | > : element_name [ HASH | class | attrib | pseudo ]*
539 | > | [ HASH | class | attrib | pseudo ]+
540 | > ;
541 | > class
542 | > : '.' IDENT
543 | > ;
544 | > element_name
545 | > : IDENT | '*'
546 | > ;
547 | > attrib
548 | > : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
549 | > [ IDENT | STRING ] S* ] ']'
550 | > ;
551 | > pseudo
552 | > : ':' [ IDENT | FUNCTION S* [IDENT S*] ')' ]
553 | > ;
554 | > ```
555 |
556 | Explanation: A ruleset is this structure:
557 |
558 | > ```lang-css
559 | > div.error, a.error {
560 | > color:red;
561 | > font-weight:bold;
562 | > }
563 | > ```
564 |
565 | div.error and a.error are selectors. The part inside the curly braces contains the rules that are applied by this ruleset. This structure is defined formally in this definition:
566 |
567 | > ```lang-bnf
568 | > ruleset
569 | > : selector [ ',' S* selector ]*
570 | > '{' S* declaration [ ';' S* declaration ]* '}' S*
571 | > ;
572 | > ```
573 |
574 | This means a ruleset is a selector or optionally a number of selectors separated by a comma and spaces (S stands for white space). A ruleset contains curly braces and inside them a declaration or optionally a number of declarations separated by a semicolon. "declaration" and "selector" will be defined in the following BNF definitions.
575 |
576 | ### WebKit CSS parser
577 |
578 | WebKit uses [Flex and Bison](#parser-generators) parser generators to create parsers automatically from the CSS grammar files. As you recall from the parser introduction, Bison creates a bottom up shift-reduce parser. Firefox uses a top down parser written manually. In both cases each CSS file is parsed into a StyleSheet object. Each object contains CSS rules. The CSS rule objects contain selector and declaration objects and other objects corresponding to CSS grammar.
579 |
580 | 
581 |
582 | **Figure : parsing CSS**
583 |
584 | ## The order of processing scripts and style sheets
585 |
586 | ### Scripts
587 |
588 | The model of the web is synchronous. Authors expect scripts to be parsed and executed immediately when the parser reaches a tag. The parsing of the document halts until the script has been executed. If the script is external then the resource must first be fetched from the network--this is also done synchronously, and parsing halts until the resource is fetched. This was the model for many years and is also specified in HTML4 and 5 specifications. Authors can add the "defer" attribute to a script, in which case it will not halt document parsing and will execute after the document is parsed. HTML5 adds an option to mark the script as asynchronous so it will be parsed and executed by a different thread.
589 |
590 | ### Speculative parsing
591 |
592 | Both WebKit and Firefox do this optimization. While executing scripts, another thread parses the rest of the document and finds out what other resources need to be loaded from the network and loads them. In this way, resources can be loaded on parallel connections and overall speed is improved. Note: the speculative parser only parses references to external resources like external scripts, style sheets and images: it doesn't modify the DOM tree--that is left to the main parser.
593 |
594 | ### Style sheets
595 |
596 | Style sheets on the other hand have a different model. Conceptually it seems that since style sheets don't change the DOM tree, there is no reason to wait for them and stop the document parsing. There is an issue, though, of scripts asking for style information during the document parsing stage. If the style is not loaded and parsed yet, the script will get wrong answers and apparently this caused lots of problems. It seems to be an edge case but is quite common. Firefox blocks all scripts when there is a style sheet that is still being loaded and parsed. WebKit blocks scripts only when they try to access certain style properties that may be affected by unloaded style sheets.
597 |
598 | ## Render tree construction
599 |
600 | While the DOM tree is being constructed, the browser constructs another tree, the render tree. This tree is of visual elements in the order in which they will be displayed. It is the visual representation of the document. The purpose of this tree is to enable painting the contents in their correct order.
601 |
602 | Firefox calls the elements in the render tree "frames". WebKit uses the term renderer or render object.\
603 | A renderer knows how to lay out and paint itself and its children.\
604 | WebKit's RenderObject class, the base class of the renderers, has the following definition:
605 |
606 | > ```lang-css
607 | > class RenderObject{
608 | > virtual void layout();
609 | > virtual void paint(PaintInfo);
610 | > virtual void rect repaintRect();
611 | > Node* node; //the DOM node
612 | > RenderStyle* style; // the computed style
613 | > RenderLayer\* containgLayer; //the containing z-index layer
614 | > }
615 | > ```
616 |
617 | Each renderer represents a rectangular area usually corresponding to a node's CSS box, as described by the CSS2 spec. It includes geometric information like width, height and position.\
618 | The box type is affected by the "display" value of the style attribute that is relevant to the node (see the [style computation](#style-computation) section). Here is WebKit code for deciding what type of renderer should be created for a DOM node, according to the display attribute:
619 |
620 | > ```lang-css
621 | > RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
622 | > {
623 | > Document* doc = node->document();
624 | > RenderArena* arena = doc->renderArena();
625 | > ...
626 | > RenderObject* o = 0;
627 | >
628 | > switch (style->display()) {
629 | > case NONE:
630 | > break;
631 | > case INLINE:
632 | > o = new (arena) RenderInline(node);
633 | > break;
634 | > case BLOCK:
635 | > o = new (arena) RenderBlock(node);
636 | > break;
637 | > case INLINE-BLOCK:
638 | > o = new (arena) RenderBlock(node);
639 | > break;
640 | > case LIST-ITEM:
641 | > o = new (arena) RenderListItem(node);
642 | > break;
643 | > ...
644 | > }
645 | > return o;
646 | > }
647 | > ```
648 |
649 | The element type is also considered: for example, form controls and tables have special frames.\
650 | In WebKit if an element wants to create a special renderer, it will override the `createRenderer()` method. The renderers point to style objects that contains non geometric information.
651 |
652 | ### The render tree relation to the DOM tree
653 |
654 | The renderers correspond to DOM elements, but the relation is not one to one. Non-visual DOM elements will not be inserted in the render tree. An example is the "head" element. Also elements whose display value was assigned to "none" will not appear in the tree (whereas elements with "hidden" visibility will appear in the tree).
655 |
656 | There are DOM elements which correspond to several visual objects. These are usually elements with complex structure that cannot be described by a single rectangle. For example, the "select" element has three renderers: one for the display area, one for the drop down list box and one for the button. Also when text is broken into multiple lines because the width is not sufficient for one line, the new lines will be added as extra renderers.\
657 | Another example of multiple renderers is broken HTML. According to the CSS spec an inline element must contain either only block elements or only inline elements. In the case of mixed content, anonymous block renderers will be created to wrap the inline elements.
658 |
659 | Some render objects correspond to a DOM node but not in the same place in the tree. Floats and absolutely positioned elements are out of flow, placed in a different part of the tree, and mapped to the real frame. A placeholder frame is where they should have been.
660 |
661 | 
662 |
663 | **Figure : The render tree and the corresponding DOM tree ([3.1](#3-1)). The "Viewport" is the initial containing block. In WebKit it will be the "RenderView" object**
664 |
665 | #### The flow of constructing the tree
666 |
667 | In Firefox, the presentation is registered as a listener for DOM updates. The presentation delegates frame creation to the `FrameConstructor` and the constructor resolves style (see [style computation](#style)) and creates a frame.
668 |
669 | In WebKit the process of resolving the style and creating a renderer is called "attachment". Every DOM node has an "attach" method. Attachment is synchronous, node insertion to the DOM tree calls the new node "attach" method.
670 |
671 | Processing the html and body tags results in the construction of the render tree root. The root render object corresponds to what the CSS spec calls the containing block: the top most block that contains all other blocks. Its dimensions are the viewport: the browser window display area dimensions. Firefox calls it `ViewPortFrame` and WebKit calls it `RenderView`. This is the render object that the document points to. The rest of the tree is constructed as a DOM nodes insertion.
672 |
673 | See [the CSS2 spec on the processing model](http://www.w3.org/TR/CSS21/intro.html#processing-model).
674 |
675 | ### Style Computation
676 |
677 | Building the render tree requires calculating the visual properties of each render object. This is done by calculating the style properties of each element.
678 |
679 | The style includes style sheets of various origins, inline style elements and visual properties in the HTML (like the "bgcolor" property).The later is translated to matching CSS style properties.
680 |
681 | The origins of style sheets are the browser's default style sheets, the style sheets provided by the page author and user style sheets--these are style sheets provided by the browser user (browsers let you define your favorite styles. In Firefox, for instance, this is done by placing a style sheet in the "Firefox Profile" folder).
682 |
683 | Style computation brings up a few difficulties:
684 |
685 | 1. Style data is a very large construct, holding the numerous style properties, this can cause memory problems.
686 | 2. Finding the matching rules for each element can cause performance issues if it's not optimized. Traversing the entire rule list for each element to find matches is a heavy task. Selectors can have complex structure that can cause the matching process to start on a seemingly promising path that is proven to be futile and another path has to be tried.
687 |
688 | For example--this compound selector:
689 |
690 | > ```lang-html
691 | > div div div div{
692 | > ...
693 | > }
694 | > ```
695 |
696 | Means the rules apply to a `
` who is the descendant of 3 divs. Suppose you want to check if the rule applies for a given `
` element. You choose a certain path up the tree for checking. You may need to traverse the node tree up just to find out there are only two divs and the rule does not apply. You then need to try other paths in the tree.
697 |
698 | 3. Applying the rules involves quite complex cascade rules that define the hierarchy of the rules.
699 |
700 | Let's see how the browsers face these issues:
701 |
702 | ### Sharing style data
703 |
704 | WebKit nodes references style objects (RenderStyle). These objects can be shared by nodes in some conditions. The nodes are siblings or cousins and:
705 |
706 | 1. The elements must be in the same mouse state (e.g., one can't be in :hover while the other isn't)
707 | 2. Neither element should have an id
708 | 3. The tag names should match
709 | 4. The class attributes should match
710 | 5. The set of mapped attributes must be identical
711 | 6. The link states must match
712 | 7. The focus states must match
713 | 8. Neither element should be affected by attribute selectors, where affected is defined as having any selector match that uses an attribute selector in any position within the selector at all
714 | 9. There must be no inline style attribute on the elements
715 | 10. There must be no sibling selectors in use at all. WebCore simply throws a global switch when any sibling selector is encountered and disables style sharing for the entire document when they are present. This includes the + selector and selectors like :first-child and :last-child.
716 |
717 | ### Firefox rule tree
718 |
719 | Firefox has two extra trees for easier style computation: the rule tree and style context tree. WebKit also has style objects but they are not stored in a tree like the style context tree, only the DOM node points to its relevant style.
720 |
721 | 
722 |
723 | **Figure : Firefox style context tree([2.2](#2-2))**
724 |
725 | The style contexts contain end values. The values are computed by applying all the matching rules in the correct order and performing manipulations that transform them from logical to concrete values. For example, if the logical value is a percentage of the screen it will be calculated and transformed to absolute units. The rule tree idea is really clever. It enables sharing these values between nodes to avoid computing them again. This also saves space.
726 |
727 | All the matched rules are stored in a tree. The bottom nodes in a path have higher priority. The tree contains all the paths for rule matches that were found. Storing the rules is done lazily. The tree isn't calculated at the beginning for every node, but whenever a node style needs to be computed the computed paths are added to the tree.
728 |
729 | The idea is to see the tree paths as words in a lexicon. Lets say we already computed this rule tree:
730 |
731 | 
732 |
733 | Suppose we need to match rules for another element in the content tree, and find out the matched rules (in the correct order) are B-E-I. We already have this path in the tree because we already computed path A-B-E-I-L. We will now have less work to do.
734 |
735 | Let's see how the tree saves us work.
736 |
737 | ### Division into structs
738 |
739 | The style contexts are divided into structs. Those structs contain style information for a certain category like border or color. All the properties in a struct are either inherited or non inherited. Inherited properties are properties that unless defined by the element, are inherited from its parent. Non inherited properties (called "reset" properties) use default values if not defined.
740 |
741 | The tree helps us by caching entire structs (containing the computed end values) in the tree. The idea is that if the bottom node didn't supply a definition for a struct, a cached struct in an upper node can be used.
742 |
743 | ### Computing the style contexts using the rule tree
744 |
745 | When computing the style context for a certain element, we first compute a path in the rule tree or use an existing one. We then begin to apply the rules in the path to fill the structs in our new style context. We start at the bottom node of the path--the one with the highest precedence (usually the most specific selector) and traverse the tree up until our struct is full. If there is no specification for the struct in that rule node, then we can greatly optimize--we go up the tree until we find a node that specifies it fully and simply point to it--that's the best optimization--the entire struct is shared. This saves computation of end values and memory.\
746 | If we find partial definitions we go up the tree until the struct is filled.
747 |
748 | If we didn't find any definitions for our struct then, in case the struct is an "inherited" type, we point to the struct of our parent in the **context tree**. In this case we also succeeded in sharing structs. If it's a reset struct then default values will be used.
749 |
750 | If the most specific node does add values then we need to do some extra calculations for transforming it to actual values. We then cache the result in the tree node so it can be used by children.
751 |
752 | In case an element has a sibling or a brother that points to the same tree node then the **entire style context** can be shared between them.
753 |
754 | Lets see an example: Suppose we have this HTML
755 |
756 | > ```lang-html
757 | >
758 | >
759 | >
760 | >
761 | >
this is a big error this is also a very big error error
762 | >
763 | >
another error
764 | >
765 | >
766 | >
767 | > ```
768 |
769 | And the following rules:
770 |
771 | > ```lang-html
772 | > 1. div {margin:5px;color:black}
773 | > 2. .err {color:red}
774 | > 3. .big {margin-top:3px}
775 | > 4. div span {margin-bottom:4px}
776 | > 5. #div1 {color:blue}
777 | > 6. #div2 {color:green}
778 | > ```
779 |
780 | To simplify things let's say we need to fill out only two structs: the color struct and the margin struct. The color struct contains only one member: the color The margin struct contains the four sides.\
781 | The resulting rule tree will look like this (the nodes are marked with the node name: the number of the rule they point at):
782 |
783 | 
784 |
785 | **Figure : The rule tree**
786 |
787 | The context tree will look like this (node name: rule node they point to):
788 |
789 | 
790 |
791 | **Figure : The context tree**
792 |
793 | Suppose we parse the HTML and get to the second
tag. We need to create a style context for this node and fill its style structs.\
794 | We will match the rules and discover that the matching rules for the
are 1, 2 and 6. This means there is already an existing path in the tree that our element can use and we just need to add another node to it for rule 6 (node F in the rule tree).\
795 | We will create a style context and put it in the context tree. The new style context will point to node F in the rule tree.
796 |
797 | We now need to fill the style structs. We will begin by filling out the margin struct. Since the last rule node (F) doesn't add to the margin struct, we can go up the tree until we find a cached struct computed in a previous node insertion and use it. We will find it on node B, which is the uppermost node that specified margin rules.
798 |
799 | We do have a definition for the color struct, so we can't use a cached struct. Since color has one attribute we don't need to go up the tree to fill other attributes. We will compute the end value (convert string to RGB etc) and cache the computed struct on this node.
800 |
801 | The work on the second element is even easier. We will match the rules and come to the conclusion that it points to rule G, like the previous span. Since we have siblings that point to the same node, we can share the entire style context and just point to the context of the previous span.
802 |
803 | For structs that contain rules that are inherited from the parent, caching is done on the context tree (the color property is actually inherited, but Firefox treats it as reset and caches it on the rule tree).\
804 | For instance if we added rules for fonts in a paragraph:
805 |
806 | > ```lang-css
807 | > p {font-family: Verdana; font size: 10px; font-weight: bold}
808 | > ```
809 |
810 | Then the paragraph element, which is a child of the div in the context tree, could have shared the same font struct as his parent. This is if no font rules were specified for the paragraph.
811 |
812 | In WebKit, who does not have a rule tree, the matched declarations are traversed four times. First non-important high priority properties are applied (properties that should be applied first because others depend on them, such as display), then high priority important, then normal priority non-important, then normal priority important rules. This means that properties that appear multiple times will be resolved according to the correct cascade order. The last wins.
813 |
814 | So to summarize: sharing the style objects (entirely or some of the structs inside them) solves issues [1](#issue1) and [3](#issue3). The Firefox rule tree also helps in applying the properties in the correct order.
815 |
816 | ### Manipulating the rules for an easy match
817 |
818 | There are several sources for style rules:
819 |
820 | - CSS rules, either in external style sheets or in style elements.
821 |
822 | > ```lang-css
823 | > p {color: blue}
824 | > ```
825 |
826 | - Inline style attributes like
827 |
828 | > ```lang-html
829 | >
830 | > ```
831 |
832 | - HTML visual attributes (which are mapped to relevant style rules)
833 |
834 | > ```lang-html
835 | >
836 | > ```
837 |
838 | The last two are easily matched to the element since he owns the style attributes and HTML attributes can be mapped using the element as the key.
839 |
840 | As noted previously in [issue #2](#issue2), the CSS rule matching can be trickier. To solve the difficulty, the rules are manipulated for easier access.
841 |
842 | After parsing the style sheet, the rules are added to one of several hash maps, according to the selector. There are maps by id, by class name, by tag name and a general map for anything that doesn't fit into those categories. If the selector is an id, the rule will be added to the id map, if it's a class it will be added to the class map etc.\
843 | This manipulation makes it much easier to match rules. There is no need to look in every declaration: we can extract the relevant rules for an element from the maps. This optimization eliminates 95+% of the rules, so that they need not even be considered during the matching process([4.1](#4-1)).
844 |
845 | Let's see for example the following style rules:
846 |
847 | > ```lang-css
848 | > p.error {color: red}
849 | > #messageDiv {height: 50px}
850 | > div {margin: 5px}
851 | > ```
852 |
853 | The first rule will be inserted into the class map. The second into the id map and the third into the tag map.\
854 | For the following HTML fragment;
855 |
856 | > ```lang-html
857 | >
an error occurred
858 | >
this is a message
859 | > ```
860 |
861 | We will first try to find rules for the p element. The class map will contain an "error" key under which the rule for "p.error" is found. The div element will have relevant rules in the id map (the key is the id) and the tag map. So the only work left is finding out which of the rules that were extracted by the keys really match.\
862 | For example if the rule for the div was
863 |
864 | > ```lang-css
865 | > table div {margin: 5px}
866 | > ```
867 |
868 | it will still be extracted from the tag map, because the key is the rightmost selector, but it would not match our div element, who does not have a table ancestor.
869 |
870 | Both WebKit and Firefox do this manipulation.
871 |
872 | ### Applying the rules in the correct cascade order
873 |
874 | The style object has properties corresponding to every visual attribute (all CSS attributes but more generic). If the property is not defined by any of the matched rules, then some properties can be inherited by the parent element style object. Other properties have default values.
875 |
876 | The problem begins when there is more than one definition--here comes the cascade order to solve the issue.
877 |
878 | ### Style sheet cascade order
879 |
880 | A declaration for a style property can appear in several style sheets, and several times inside a style sheet. This means the order of applying the rules is very important. This is called the "cascade" order. According to CSS2 spec, the cascade order is (from low to high):
881 |
882 | 1. Browser declarations
883 | 2. User normal declarations
884 | 3. Author normal declarations
885 | 4. Author important declarations
886 | 5. User important declarations
887 |
888 | The browser declarations are least important and the user overrides the author only if the declaration was marked as important. Declarations with the same order will be sorted by [specificity](#Specificity) and then the order they are specified. The HTML visual attributes are translated to matching CSS declarations . They are treated as author rules with low priority.
889 |
890 | ### Specificity
891 |
892 | The selector specificity is defined by the [CSS2 specification](http://www.w3.org/TR/CSS2/cascade.html#specificity) as follows:
893 |
894 | - count 1 if the declaration it is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a)
895 | - count the number of ID attributes in the selector (= b)
896 | - count the number of other attributes and pseudo-classes in the selector (= c)
897 | - count the number of element names and pseudo-elements in the selector (= d)
898 |
899 | Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.
900 |
901 | The number base you need to use is defined by the highest count you have in one of the categories.\
902 | For example, if a=14 you can use hexadecimal base. In the unlikely case where a=17 you will need a 17 digits number base. The later situation can happen with a selector like this: html body div div p ... (17 tags in your selector.. not very likely).
903 |
904 | Some examples:
905 |
906 | > ```lang-css
907 | > * {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
908 | > li {} /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
909 | > li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
910 | > ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
911 | > ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
912 | > h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
913 | > ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
914 | > li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
915 | > #x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
916 | > style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */
917 | > ```
918 |
919 | ### Sorting the rules
920 |
921 | After the rules are matched, they are sorted according to the cascade rules. WebKit uses bubble sort for small lists and merge sort for big ones. WebKit implements sorting by overriding the ">" operator for the rules:
922 |
923 | > ```lang-c
924 | > static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
925 | > {
926 | > int spec1 = r1.selector()->specificity();
927 | > int spec2 = r2.selector()->specificity();
928 | > return (spec1 == spec2) : r1.position() > r2.position() : spec1 > spec2;
929 | > }
930 | > ```
931 |
932 | ### Gradual process
933 |
934 | WebKit uses a flag that marks if all top level style sheets (including @imports) have been loaded. If the style is not fully loaded when attaching, place holders are used and it is marked in the document, and they will be recalculated once the style sheets were loaded.
935 |
936 | ## Layout
937 |
938 | When the renderer is created and added to the tree, it does not have a position and size. Calculating these values is called layout or reflow.
939 |
940 | HTML uses a flow based layout model, meaning that most of the time it is possible to compute the geometry in a single pass. Elements later `in the flow'' typically do not affect the geometry of elements that are earlier `in the flow'', so layout can proceed left-to-right, top-to-bottom through the document. There are exceptions: for example, HTML tables may require more than one pass ([3.5](#3-5)).
941 |
942 | The coordinate system is relative to the root frame. Top and left coordinates are used.
943 |
944 | Layout is a recursive process. It begins at the root renderer, which corresponds to the `` element of the HTML document. Layout continues recursively through some or all of the frame hierarchy, computing geometric information for each renderer that requires it.
945 |
946 | The position of the root renderer is 0,0 and its dimensions are the viewport--the visible part of the browser window.
947 |
948 | All renderers have a "layout" or "reflow" method, each renderer invokes the layout method of its children that need layout.
949 |
950 | ### Dirty bit system
951 |
952 | In order not to do a full layout for every small change, browsers use a "dirty bit" system. A renderer that is changed or added marks itself and its children as "dirty": needing layout.
953 |
954 | There are two flags: "dirty", and "children are dirty" which means that although the renderer itself may be OK, it has at least one child that needs a layout.
955 |
956 | ### Global and incremental layout
957 |
958 | Layout can be triggered on the entire render tree--this is "global" layout. This can happen as a result of:
959 |
960 | 1. A global style change that affects all renderers, like a font size change.
961 | 2. As a result of a screen being resized
962 |
963 | Layout can be incremental, only the dirty renderers will be laid out (this can cause some damage which will require extra layouts).\
964 | Incremental layout is triggered (asynchronously) when renderers are dirty. For example when new renderers are appended to the render tree after extra content came from the network and was added to the DOM tree.
965 |
966 | 
967 |
968 | **Figure : Incremental layout--only dirty renderers and their children are laid out ([3.6](#3-6))**
969 |
970 | ### Asynchronous and Synchronous layout
971 |
972 | Incremental layout is done asynchronously. Firefox queues "reflow commands" for incremental layouts and a scheduler triggers batch execution of these commands. WebKit also has a timer that executes an incremental layout--the tree is traversed and "dirty" renderers are layout out.\
973 | Scripts asking for style information, like "offsetHeight" can trigger incremental layout synchronously.\
974 | Global layout will usually be triggered synchronously.\
975 | Sometimes layout is triggered as a callback after an initial layout because some attributes, like the scrolling position changed.
976 |
977 | ### Optimizations
978 |
979 | When a layout is triggered by a "resize" or a change in the renderer position(and not size), the renders sizes are taken from a cache and not recalculated..\
980 | In some cases only a sub tree is modified and layout does not start from the root. This can happen in cases where the change is local and does not affect its surroundings--like text inserted into text fields (otherwise every keystroke would trigger a layout starting from the root).
981 |
982 | ### The layout process
983 |
984 | The layout usually has the following pattern:
985 |
986 | 1. Parent renderer determines its own width.
987 | 2. Parent goes over children and:
988 | 1. Place the child renderer (sets its x and y).
989 | 2. Calls child layout if needed--they are dirty or we are in a global layout, or for some other reason--which calculates the child's height.
990 | 3. Parent uses children's accumulative heights and the heights of margins and padding to set its own height--this will be used by the parent renderer's parent.
991 | 4. Sets its dirty bit to false.
992 |
993 | Firefox uses a "state" object(nsHTMLReflowState) as a parameter to layout (termed "reflow"). Among others the state includes the parents width.\
994 | The output of the Firefox layout is a "metrics" object(nsHTMLReflowMetrics). It will contain the renderer computed height.
995 |
996 | ### Width calculation
997 |
998 | The renderer's width is calculated using the container block's width, the renderer's style "width" property, the margins and borders.\
999 | For example the width of the following div:
1000 |
1001 | > ```lang-html
1002 | >
1003 | > ```
1004 |
1005 | Would be calculated by WebKit as the following(class RenderBox method calcWidth):
1006 |
1007 | - The container width is the maximum of the containers availableWidth and 0. The availableWidth in this case is the contentWidth which is calculated as:
1008 |
1009 | > ```lang-css
1010 | > clientWidth() - paddingLeft() - paddingRight()
1011 | > ```
1012 |
1013 | clientWidth and clientHeight represent the interior of an object excluding border and scrollbar.
1014 |
1015 | - The elements width is the "width" style attribute. It will be calculated as an absolute value by computing the percentage of the container width.
1016 | - The horizontal borders and paddings are now added.
1017 |
1018 | So far this was the calculation of the "preferred width". Now the minimum and maximum widths will be calculated.\
1019 | If the preferred width is greater then the maximum width, the maximum width is used. If it is less then the minimum width (the smallest unbreakable unit) then the minimum width is used.
1020 |
1021 | The values are cached in case a layout is needed, but the width does not change.
1022 |
1023 | ### Line Breaking
1024 |
1025 | When a renderer in the middle of a layout decides that it needs to break, the renderer stops and propagates to the layout's parent that it needs to be broken. The parent creates the extra renderers and calls layout on them.
1026 |
1027 | ## Painting
1028 |
1029 | In the painting stage, the render tree is traversed and the renderer's "paint()" method is called to display content on the screen. Painting uses the UI infrastructure component.
1030 |
1031 | ### Global and Incremental
1032 |
1033 | Like layout, painting can also be global--the entire tree is painted--or incremental. In incremental painting, some of the renderers change in a way that does not affect the entire tree. The changed renderer invalidates its rectangle on the screen. This causes the OS to see it as a "dirty region" and generate a "paint" event. The OS does it cleverly and coalesces several regions into one. In Chrome it is more complicated because the renderer is in a different process then the main process. Chrome simulates the OS behavior to some extent. The presentation listens to these events and delegates the message to the render root. The tree is traversed until the relevant renderer is reached. It will repaint itself (and usually its children).
1034 |
1035 | ### The painting order
1036 |
1037 | [CSS2 defines the order of the painting process](http://www.w3.org/TR/CSS21/zindex.html). This is actually the order in which the elements are stacked in the [stacking contexts](#stackingcontext). This order affects painting since the stacks are painted from back to front. The stacking order of a block renderer is:
1038 |
1039 | 1. background color
1040 | 2. background image
1041 | 3. border
1042 | 4. children
1043 | 5. outline
1044 |
1045 | ### Firefox display list
1046 |
1047 | Firefox goes over the render tree and builds a display list for the painted rectangular. It contains the renderers relevant for the rectangular, in the right painting order (backgrounds of the renderers, then borders etc). That way the tree needs to be traversed only once for a repaint instead of several times--painting all backgrounds, then all images, then all borders etc.
1048 |
1049 | Firefox optimizes the process by not adding elements that will be hidden, like elements completely beneath other opaque elements.
1050 |
1051 | #### WebKit rectangle storage
1052 |
1053 | Before repainting, WebKit saves the old rectangle as a bitmap. It then paints only the delta between the new and old rectangles.
1054 |
1055 | ### Dynamic changes
1056 |
1057 | The browsers try to do the minimal possible actions in response to a change. So changes to an element's color will cause only repaint of the element. Changes to the element position will cause layout and repaint of the element, its children and possibly siblings. Adding a DOM node will cause layout and repaint of the node. Major changes, like increasing font size of the "html" element, will cause invalidation of caches, relayout and repaint of the entire tree.
1058 |
1059 | ### The rendering engine's threads
1060 |
1061 | The rendering engine is single threaded. Almost everything, except network operations, happens in a single thread. In Firefox and Safari this is the main thread of the browser. In Chrome it's the tab process main thread.\
1062 | Network operations can be performed by several parallel threads. The number of parallel connections is limited (usually 2--6 connections).
1063 |
1064 | ### Event loop
1065 |
1066 | The browser main thread is an event loop. It's an infinite loop that keeps the process alive. It waits for events (like layout and paint events) and processes them. This is Firefox code for the main event loop:
1067 |
1068 | > ```lang-c
1069 | > while (!mExiting) NS-ProcessNextEvent(thread);
1070 | > ```
1071 |
1072 | ## CSS2 visual model
1073 |
1074 | ### The canvas
1075 |
1076 | According to the [CSS2 specification](http://www.w3.org/TR/CSS21/intro.html#processing-model), the term canvas describes "the space where the formatting structure is rendered": where the browser paints the content. The canvas is infinite for each dimension of the space but browsers choose an initial width based on the dimensions of the viewport.
1077 |
1078 | According to [www.w3.org/TR/CSS2/zindex.html](http://www.w3.org/TR/CSS2/zindex.html), the canvas is transparent if contained within another, and given a browser defined color if it is not.
1079 |
1080 | ### CSS Box model
1081 |
1082 | The [CSS box model](http://www.w3.org/TR/CSS2/box.html) describes the rectangular boxes that are generated for elements in the document tree and laid out according to the visual formatting model.\
1083 | Each box has a content area (e.g. text, an image, etc.) and optional surrounding padding, border, and margin areas.
1084 |
1085 | 
1086 |
1087 | **Figure : CSS2 box model**
1088 |
1089 | Each node generates 0..n such boxes.\
1090 | All elements have a "display" property that determines the type of box that will be generated.
1091 |
1092 | Examples:
1093 |
1094 | > ```lang-html
1095 | > block: generates a block box.
1096 | > inline: generates one or more inline boxes.
1097 | > none: no box is generated.
1098 | > ```
1099 |
1100 | The default is inline but the browser style sheet may set other defaults. For example: the default display for the "div" element is block.\
1101 | You can find a default style sheet example here: [www.w3.org/TR/CSS2/sample.html](http://www.w3.org/TR/CSS2/sample.html)
1102 |
1103 | ### Positioning scheme
1104 |
1105 | There are three schemes:
1106 |
1107 | 1. Normal: the object is positioned according to its place in the document. This means its place in the render tree is like its place in the DOM tree and laid out according to its box type and dimensions
1108 | 2. Float: the object is first laid out like normal flow, then moved as far left or right as possible
1109 | 3. Absolute: the object is put in the render tree in a different place than in the DOM tree
1110 |
1111 | The positioning scheme is set by the "position" property and the "float" attribute.
1112 |
1113 | - static and relative cause a normal flow
1114 | - absolute and fixed cause absolute positioning
1115 |
1116 | In static positioning no position is defined and the default positioning is used. In the other schemes, the author specifies the position: top, bottom, left, right.
1117 |
1118 | The way the box is laid out is determined by:
1119 |
1120 | - Box type
1121 | - Box dimensions
1122 | - Positioning scheme
1123 | - External information such as image size and the size of the screen
1124 |
1125 | ### Box types
1126 |
1127 | Block box: forms a block--has its own rectangle in the browser window.
1128 |
1129 | 
1130 |
1131 | **Figure : Block box**
1132 |
1133 | Inline box: does not have its own block, but is inside a containing block.
1134 |
1135 | 
1136 |
1137 | **Figure : Inline boxes**
1138 |
1139 | Blocks are formatted vertically one after the other. Inlines are formatted horizontally.
1140 |
1141 | 
1142 |
1143 | **Figure : Block and Inline formatting**
1144 |
1145 | Inline boxes are put inside lines or "line boxes". The lines are at least as tall as the tallest box but can be taller, when the boxes are aligned "baseline"--meaning the bottom part of an element is aligned at a point of another box other then the bottom. If the container width is not enough, the inlines will be put on several lines. This is usually what happens in a paragraph.
1146 |
1147 | 
1148 |
1149 | **Figure: Lines**
1150 |
1151 | ### Positioning
1152 |
1153 | #### Relative
1154 |
1155 | Relative positioning--positioned like usual and then moved by the required delta.
1156 |
1157 | 
1158 |
1159 | **Figure: Relative positioning**
1160 |
1161 | #### Floats
1162 |
1163 | A float box is shifted to the left or right of a line. The interesting feature is that the other boxes flow around it. The HTML:
1164 |
1165 | > ```lang-html
1166 | >
1167 | >
1168 | > Lorem ipsum dolor sit amet, consectetuer...
1169 | >
1170 | > ```
1171 |
1172 | Will look like:
1173 |
1174 | 
1175 |
1176 | **Figure : Float**
1177 |
1178 | #### Absolute and fixed
1179 |
1180 | The layout is defined exactly regardless of the normal flow. The element does not participate in the normal flow. The dimensions are relative to the container. In fixed, the container is the viewport.
1181 |
1182 | 
1183 |
1184 | **Figure : Fixed positioning**
1185 |
1186 | Note: the fixed box will not move even when the document is scrolled!
1187 |
1188 | ### Layered representation
1189 |
1190 | This is specified by the z-index CSS property. It represents the third dimension of the box: its position along the "z axis".
1191 |
1192 | The boxes are divided into stacks (called stacking contexts). In each stack the back elements will be painted first and the forward elements on top, closer to the user. In case of overlap the foremost element will hide the former element.\
1193 | The stacks are ordered according to the z-index property. Boxes with "z-index" property form a local stack. The viewport has the outer stack.
1194 |
1195 | Example:
1196 |
1197 | > ```lang-html
1198 | >
1205 | >