2025-12-28T12:00:00+01:00https://friendlybit.comFriendly Bit - Web development blogFriendly Bit is a blog by Emil Stenström, a Swedish web developer that occasionally gets ideas of how to improve the internet.JustHTML is now safe-by-default2025-12-28T12:00:00+01:002025-12-28T12:00:00+01:00http://friendlybit.com/python/justhtml-sanitization/Emil StenströmIf you accept HTML from users (comments, profiles, CMS fields), you eventually hit the same problem: You want to keep some markup. You really don’t want to...
<p>If you accept HTML from users (comments, profiles, CMS fields), you eventually hit the same problem:</p>
<ul>
<li>You want to keep <em>some</em> markup.</li>
<li>You really don’t want to ship an <a href="https://learn.snyk.io/lesson/xss/?ecosystem=javascript">XSS</a>.</li>
</ul>
<p>That’s why JustHTML now includes a built-in, policy-driven HTML sanitizer, and why serialization is <strong>safe-by-default</strong>.</p>
<h2 id="safe-by-default-serialization">Safe-by-default serialization<a href="#safe-by-default-serialization">#</a></h2>
<p>JustHTML sanitizes when you serialize to HTML or Markdown:</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">justhtml</span><span class="w"> </span><span class="kn">import</span> <span class="n">JustHTML</span>
<span class="n">user_html</span> <span class="o">=</span> <span class="p">(</span>
<span class="s1">'<p>Hello <b>world</b> <script>alert(1)</script> '</span>
<span class="s1">'<a href="javascript:alert(1)">bad</a> '</span>
<span class="s1">'<a href="https://example.com/?a=1&b=2">ok</a></p>'</span>
<span class="p">)</span>
<span class="n">doc</span> <span class="o">=</span> <span class="n">JustHTML</span><span class="p">(</span><span class="n">user_html</span><span class="p">,</span> <span class="n">fragment</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">to_html</span><span class="p">())</span>
<span class="nb">print</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">to_markdown</span><span class="p">())</span>
</pre></div>
<p>This drops <code><script></code> and strips dangerous URLs:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">p</span><span class="p">></span>Hello <span class="p"><</span><span class="nt">b</span><span class="p">></span>world<span class="p"></</span><span class="nt">b</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span><span class="p">></span>bad<span class="p"></</span><span class="nt">a</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"https://example.com/?a=1&amp;b=2"</span><span class="p">></span>ok<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">p</span><span class="p">></span>
</pre></div>
<div class="highlight" data-language="MARKDOWN"><pre><span></span>Hello <span class="gs">**world**</span> [bad] [<span class="nt">ok</span>](<span class="na">https://example.com/?a=1&b=2</span>)
</pre></div>
<h2 id="turning-it-off-trusted-input-only">Turning it off (trusted input only)<a href="#turning-it-off-trusted-input-only">#</a></h2>
<p>If the input is trusted and you want raw output, you can opt out:</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">to_html</span><span class="p">(</span><span class="n">safe</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">to_markdown</span><span class="p">(</span><span class="n">safe</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
</pre></div>
<h2 id="custom-allowlist-policies">Custom allowlist policies<a href="#custom-allowlist-policies">#</a></h2>
<p>The default policy is intentionally conservative, but you can provide your own <code>SanitizationPolicy</code>.
Here’s a small example that only allows <code>p</code>, <code>b</code>, and <code>a[href]</code>, and only allows <code>https</code> links:</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">justhtml</span><span class="w"> </span><span class="kn">import</span> <span class="n">JustHTML</span><span class="p">,</span> <span class="n">SanitizationPolicy</span><span class="p">,</span> <span class="n">UrlRule</span>
<span class="n">policy</span> <span class="o">=</span> <span class="n">SanitizationPolicy</span><span class="p">(</span>
<span class="n">allowed_tags</span><span class="o">=</span><span class="p">[</span><span class="s2">"p"</span><span class="p">,</span> <span class="s2">"b"</span><span class="p">,</span> <span class="s2">"a"</span><span class="p">],</span>
<span class="n">allowed_attributes</span><span class="o">=</span><span class="p">{</span><span class="s2">"*"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"a"</span><span class="p">:</span> <span class="p">[</span><span class="s2">"href"</span><span class="p">]},</span>
<span class="n">url_rules</span><span class="o">=</span><span class="p">{</span>
<span class="p">(</span><span class="s2">"a"</span><span class="p">,</span> <span class="s2">"href"</span><span class="p">):</span> <span class="n">UrlRule</span><span class="p">(</span><span class="n">allowed_schemes</span><span class="o">=</span><span class="p">[</span><span class="s2">"https"</span><span class="p">]),</span>
<span class="p">},</span>
<span class="p">)</span>
<span class="n">doc</span> <span class="o">=</span> <span class="n">JustHTML</span><span class="p">(</span><span class="n">user_html</span><span class="p">,</span> <span class="n">fragment</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">to_html</span><span class="p">(</span><span class="n">policy</span><span class="o">=</span><span class="n">policy</span><span class="p">))</span>
</pre></div>
<p>If you’re sanitizing a full document, safe serialization keeps <code><html></code>, <code><head></code>, and <code><body></code> wrappers.
For snippets, pass <code>fragment=True</code> to avoid implicit document wrappers.</p>
<p>There are also a couple of knobs that tend to show up in real systems:</p>
<ul>
<li>URL proxying (for example, rewriting <code>https://example.com/…</code> to <code>/proxy?url=…</code>)</li>
<li>Optional inline styles, with an allowlist of CSS properties and conservative value checks</li>
</ul>
<h2 id="why-i-built-codejusthtml-xss-benchcode">Why I built <code>justhtml-xss-bench</code><a href="#why-i-built-codejusthtml-xss-benchcode">#</a></h2>
<p>If you’ve worked on sanitizers before, you know the hard part isn’t writing a policy — it’s knowing what the browser will actually do with the result.</p>
<p>So I built a tiny benchmark harness: <code>[justhtml-xss-bench](https://github.com/EmilStenstrom/justhtml-xss-bench/)</code>.</p>
<p>What it does:</p>
<ul>
<li>Takes a payload vector and a sanitizer.</li>
<li>Sanitizes the payload.</li>
<li>Embeds the sanitized output into the initial HTML page ("server-side" style).</li>
<li>Loads it in a real Playwright browser engine.</li>
<li>Fails the case if JavaScript executes (including signals like dialogs or attempted external script fetches).</li>
</ul>
<p>It ships with <strong>7,000+ real-world XSS vectors</strong> and can be used to compare JustHTML’s output with other sanitizers.</p>
<p>If you want to explore it locally, the CLI looks like this:</p>
<div class="highlight" data-language="BASH"><pre><span></span><span class="c1"># Run all vector files in ./vectors against the default sanitizer set</span>
xssbench
<span class="c1"># Limit to one engine</span>
xssbench<span class="w"> </span>--browser<span class="w"> </span>chromium
<span class="c1"># List available sanitizers</span>
xssbench<span class="w"> </span>--list-sanitizers
<span class="c1"># Run a subset</span>
xssbench<span class="w"> </span>--vectors<span class="w"> </span>vectors/bleach.json<span class="w"> </span>--sanitizers<span class="w"> </span>noop
</pre></div>
<h2 id="threat-model-what-safe-means">Threat model (what “safe” means)<a href="#threat-model-what-safe-means">#</a></h2>
<p>JustHTML’s sanitizer aims to prevent script execution when you sanitize untrusted HTML and embed the result into an HTML document as markup.</p>
<p>It does <em>not</em> make it safe to drop the output into JavaScript string contexts, CSS contexts, URL contexts, or other non-HTML contexts — those need their own escaping/handling.</p>
<p>If you want the details, see the JustHTML sanitization documentation:</p>
<ul>
<li>https://github.com/EmilStenstrom/justhtml/blob/master/docs/sanitization.md</li>
</ul>
<p>And the benchmark harness repo:</p>
<ul>
<li>https://github.com/EmilStenstrom/justhtml-xss-bench</li>
</ul>
JustHTML: Addressing some questions2025-12-19T12:00:00+01:002025-12-19T12:00:00+01:00http://friendlybit.com/python/justhtml-faq/Emil StenströmWhen Simon Willison wrote about JustHTML [1] [2], suddenly everyone was interested in giving their view. After reading through (what I think is) all of...
<p>When Simon Willison wrote about JustHTML <a href="https://simonwillison.net/2025/Dec/14/justhtml/">[1]</a> <a href="https://simonwillison.net/2025/Dec/15/porting-justhtml/">[2]</a>, suddenly everyone was interested in giving their view. After reading through (what I think is) all of them, I thought I'd address some questions that have arisen.</p>
<h2 id="quotthis-is-a-copy-this-is-derived-workquot">"This is a copy / this is derived work!"<a href="#quotthis-is-a-copy-this-is-derived-workquot">#</a></h2>
<p>It is very unclear if JustHTML is a derived work. About halfway in I did tell the LLM to "port html5ever", but I don't think that's what the LLM did. It started from the code structure of html5ever, but much of the code was trial and error against the html5lib-tests suite. In later versions I asked it to refactor much of the code, so I don't think even the structure is there any more.</p>
<p>I asked an agent to try to find cross references between the two projects that still remain, but all it found were things that were also in the WHATWG HTML5 specification. This doesn't say it's <strong>not</strong> derivative work, but highlights that it's far from clear.</p>
<p>If you can find cases where the code is very similar (and not specifically required by spec), I would be happy to see it!</p>
<h2 id="quothe-stripped-the-authorship-laundered-the-l">"He stripped the authorship / laundered the license!"<a href="#quothe-stripped-the-authorship-laundered-the-l">#</a></h2>
<p>This wording assumes an active attempt to strip it, which is opposite of me adding the html5ever <a href="https://github.com/EmilStenstrom/justhtml/blob/master/README.md#acknowledgments">acknowledgement</a> to the JustHTML README. Just stop that nonsense. I have nothing but love for the html5ever developers. To put that to rest, I've decided to 1) add their copyright block to my license anyway and 2) <a href="https://github.com/servo/html5ever/issues/701">ask them specifically for guidance</a>. I'm looking forward to hearing their view.</p>
<p>For reference, this is the current <code>LICENSE</code> file in JustHTML:</p>
<pre>MIT License
Copyright (c) 2025 Emil Stenström
Copyright (c) 2014-2017, The html5ever Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
...
</pre><h2 id="quothe-doesnt-understand-the-codequot">"He doesn't understand the code"<a href="#quothe-doesnt-understand-the-codequot">#</a></h2>
<p>Many commenters were angry that I didn't <em>understand the code</em>. This is such an interesting take, especially in a society where not understanding is seen as weakness. We should be certain! We should know everything! But we don't. We're all fallible and walk around trying to figure things out.</p>
<p>In the specific case of the HTML5 specification, there are very few people—in the world—who understand it. HTML5 is an intricate web of algorithms, that interact in difficult-to-understand ways (see <a href="https://htmlparser.info/">htmlparser.info</a> for a great guided tour). Did you know that the tokenizer and treebuilder affect each other?</p>
<p>Luckily for us, the authors decided to <s>shame</s> help browsers interoperate by publishing the fantastic html5lib-tests suite. It's an incredible feat of engineering, with thousands of integration tests that (almost) completely test the specification.</p>
<p>Here is a representative example of the kind of input those tests test for:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">p</span><span class="p">></span>One <span class="p"><</span><span class="nt">b</span><span class="p">></span>two <span class="p"><</span><span class="nt">i</span><span class="p">></span>three<span class="p"></</span><span class="nt">b</span><span class="p">></span> four<span class="p"></</span><span class="nt">i</span><span class="p">></span> five
<span class="p"><</span><span class="nt">table</span><span class="p">><</span><span class="nt">p</span><span class="p">><</span><span class="nt">tr</span><span class="p">><</span><span class="nt">td</span><span class="p">></span>cell<span class="p"></</span><span class="nt">table</span><span class="p">></span>
<span class="p"><</span><span class="nt">svg</span><span class="p">><</span><span class="nt">foreignObject</span><span class="p">><</span><span class="nt">p</span><span class="p">></span>inside svg<span class="p"></</span><span class="nt">foreignObject</span><span class="p">></</span><span class="nt">svg</span><span class="p">></span>
</pre></div>
<p><small>That single snippet touches multiple "special" parts of the spec: mis-nested formatting elements (the adoption agency algorithm), implied end tags, table insertion mode oddities, and foreign content integration points.</small></p>
<p>What's fantastic about html5lib-tests is that it gives us a way to look at our code from the outside and see if it works or not, <strong>without us having to understand it</strong>. If this feels extreme, think of low-level code—assembler—if you will. Do you understand how it flips the transistors in your computer? I don't. And that's fine, because you have other ways to know that your code works. You don't have to go into the details.</p>
<p><strong>LLMs are quickly becoming a new layer on top of the code we write. If we can find a way to prove that it works, we don't need to understand it. That opens up whole new possibilities!</strong></p>
<h2 id="quotits-not-high-quality-code-because-it-wont">"It's not high quality code, because it won't be maintained"<a href="#quotits-not-high-quality-code-because-it-wont">#</a></h2>
<p>I'm very sure that this code is maintainable, because I have been maintaining it for a while already. As I was approaching 100% test coverage, a new HTML5 feature was added to the test suite: <code><selectedcontent></code>. This was easily supported with a couple of queries to the LLM.</p>
<p>I am planning to maintain it. The PRs are rolling in, and I have quite a clear image of where I want to take it. I think the API I've put on top of the parser is really attractive, with a very low learning curve. That's worth something, and it's missing from all the other libraries.</p>
<p>The first versions of the library were very hard to maintain, even with LLM help. When I looked under the hood there were messy nested if blocks, that mirrored some of the test data exactly. The LLM was cheating! I have not seen signs of this in the later versions of the code, and especially since LLM models got better.</p>
<hr />
<p>I'm happy that my little experiment triggered so many discussions. Overall, I think (and you are free to disagree) that having this library is a big net positive for the Python community.</p>
How I wrote JustHTML using coding agents2025-12-03T12:00:00+01:002025-12-03T12:00:00+01:00http://friendlybit.com/python/writing-justhtml-with-coding-agents/Emil StenströmI recently released JustHTML, a python-based HTML5 parser. It passes 100% of the html5lib test suite, has zero dependencies, and includes a CSS selector...
<p>I recently released <a href="https://github.com/EmilStenstrom/justhtml">JustHTML</a>, a python-based HTML5 parser. It passes 100% of the html5lib test suite, has zero dependencies, and includes a CSS selector query API. Writing it taught me a lot about how to work with coding agents effectively.</p>
<p>I thought I knew HTML going into this project, but it turns out I know nothing when it comes to parsing broken HTML5 code. That's the majority of the algorithm.</p>
<p><a href="https://hsivonen.fi/">Henri Sivonen</a>, who implemented the HTML5 parser for Firefox, called the "<a href="https://html.spec.whatwg.org/multipage/parsing.html#adoption-agency-algorithm">adoption agency algorithm</a>" (which handles misnested formatting elements) "the most complicated part of the tree builder". It involves a "<a href="https://html.spec.whatwg.org/multipage/parsing.html#list-of-active-formatting-elements">Noah's Ark</a>" clause (limiting identical elements to 3) and complex stack manipulation that breaks the standard stack model.</p>
<p>I still don't know how to solve those problems. But I still have a parser that solves those problems better than the reference implementation <a href="https://github.com/html5lib/html5lib-python">html5lib</a>. Power of AI! :)</p>
<h2 id="why-html5">Why HTML5?<a href="#why-html5">#</a></h2>
<p>When picking a project to build with coding agents, choosing one that already has a lot of tests is a great idea. HTML5 is extremely well-specified, with a long specification and thousands of treebuilder and tokenizer tests available in the <a href="https://github.com/html5lib/html5lib-tests"><code>html5lib-tests</code></a> repository.</p>
<p>When using coding agents autonomously, you need a way for them to understand their own progress. A complete test suite is perfect for that. The agent can run the tests, see what failed, and iterate until they pass.</p>
<h2 id="building-the-parser-iterations-restarts-and-per">Building the parser (iterations, restarts, and performance work)<a href="#building-the-parser-iterations-restarts-and-per">#</a></h2>
<p>Writing a full HTML5 parser is not a short one-shot problem. I have been working on this project for a couple of months on off-hours.</p>
<p>Tooling: I used plain VS Code with Github Copilot in Agent mode. I enabled automatic approval of all commands, and then added a blacklist of commands that I always wanted to approve manually. I wrote an <a href="https://github.com/EmilStenstrom/justhtml/blob/main/.github/copilot-instructions.md">agent instruction</a> that told it to keep working, and don't stop to ask questions. Worked well!</p>
<p>Here is the process it took to get here:</p>
<h3 id="a-one-shot-html5-parser-as-a-baseline">A one-shot HTML5 parser (as a baseline)<a href="#a-one-shot-html5-parser-as-a-baseline">#</a></h3>
<p>To begin, I asked the agent to write a super-basic one-shot HTML5 parser. It didn't work very well, but it was a start.</p>
<h3 id="wiring-up-codehtml5lib-testscode-lt1-pass">Wiring up <code>html5lib-tests</code> (<1% pass rate)<a href="#wiring-up-codehtml5lib-testscode-lt1-pass">#</a></h3>
<p>Next, I wired up the <code>html5lib-tests</code> and saw that we had a <1% pass rate. Yes, those tests are hard. They are the gold standard for HTML5 parsing, containing thousands of edge cases like:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">b</span><span class="p">><</span><span class="nt">p</span><span class="p">></</span><span class="nt">b</span><span class="p">></</span><span class="nt">i</span><span class="p">></span>
</pre></div>
<h3 id="iterating-to-30-coverage-refactors-and-bugfixes">Iterating to ~30% coverage (refactors and bugfixes)<a href="#iterating-to-30-coverage-refactors-and-bugfixes">#</a></h3>
<p>After that, we started iterating, slowly climbing to about 30% pass rate. This involved a lot of refactoring and fixing small bugs.</p>
<h3 id="refactoring-into-per-tag-handlers">Refactoring into per-tag handlers<a href="#refactoring-into-per-tag-handlers">#</a></h3>
<p>Once I could see the shape of the problem, I decided I liked a handler-based structure, where each tag gets its own handler. Modular structure ftw! I asked the agent to refactor and it did.</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">TagHandler</span><span class="p">:</span>
<span class="w"> </span><span class="sd">"""Base class for all tag handlers."""</span>
<span class="k">def</span><span class="w"> </span><span class="nf">handle_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">UnifiedCommentHandler</span><span class="p">(</span><span class="n">TagHandler</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Handles comments in all states."""</span>
<span class="k">def</span><span class="w"> </span><span class="nf">handle_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
<span class="n">context</span><span class="o">.</span><span class="n">insert_comment</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
</pre></div>
<h3 id="reaching-100-test-coverage-with-better-models">Reaching 100% test coverage (with better models)<a href="#reaching-100-test-coverage-with-better-models">#</a></h3>
<p>From there, we continued iterating to 100% test coverage. This took a long time, and the <a href="https://www.anthropic.com/news/claude-3-7-sonnet">Claude Sonnet 3.7</a> release was the reason we got anywhere at all.</p>
<h3 id="benchmarking-and-discovering-we-were-3x-slower">Benchmarking and discovering we were 3x slower<a href="#benchmarking-and-discovering-we-were-3x-slower">#</a></h3>
<p>With correctness handled, I set up a <a href="https://github.com/EmilStenstrom/justhtml/blob/master/benchmarks/performance.py">benchmark</a> to test how fast my parser was. I saw that I was 3x slower than <code>html5lib</code>, which is already considered slow.</p>
<h3 id="rewriting-the-tokenizer-in-rust-and-barely-matchi">Rewriting the tokenizer in Rust (and barely matching <code>html5lib</code>)<a href="#rewriting-the-tokenizer-in-rust-and-barely-matchi">#</a></h3>
<p>So I tried the obvious next move: I let an agent rewrite the tokenizer in Rust to speed things up (note: I don't know Rust). It worked, and the speed barely passed <code>html5lib</code>. It created a whole <code>rust_tokenizer</code> crate with 690 lines of Rust code in <code>lib.rs</code> that I couldn't read, but it passed the tests.</p>
<h3 id="discovering-codehtml5evercode-fast-correct">Discovering <code>html5ever</code> (fast, correct, Rust)<a href="#discovering-codehtml5evercode-fast-correct">#</a></h3>
<p>While looking for alternatives, I found <a href="https://github.com/servo/html5ever"><code>html5ever</code></a>, <a href="https://servo.org/">Servo</a>'s parsing engine. It is very correct and written from scratch in Rust to be fast.</p>
<h3 id="asking-why-build-this-at-all">Asking: why build this at all?<a href="#asking-why-build-this-at-all">#</a></h3>
<p>At that point I had the uncomfortable thought: why would the world need a slower version of <code>html5ever</code> in partial Python? What is the meaning of it all?! I almost just deleted the whole project.</p>
<h3 id="pivoting-to-porting-codehtml5evercode-logic-t">Pivoting to porting <code>html5ever</code> logic to Python<a href="#pivoting-to-porting-codehtml5evercode-logic-t">#</a></h3>
<p>Instead of quitting, I considered writing a Python interface against <code>html5ever</code>, but decided I didn't like the hassle of a library requiring installing binary files. So I went pure Python again, but with a faster approach: what if I port the <code>html5ever</code> logic to Python? Shouldn't that be faster than the existing Python libraries? I decided to throw all previous work away.</p>
<h3 id="restarting-from-scratch-again">Restarting from scratch (again)<a href="#restarting-from-scratch-again">#</a></h3>
<p>So I started over from <1% test coverage and iterated with the same set of tests all the way up to 100%. This time I asked it to cross reference the Rust codebase in the beginning. It was tedious work, doing the same thing over again.</p>
<h3 id="still-slower-than-codehtml5libcode">Still slower than <code>html5lib</code><a href="#still-slower-than-codehtml5libcode">#</a></h3>
<p>Unfortunately, I ran the benchmark on the new codebase and found that it was <em>still</em> slower than <code>html5lib</code>.</p>
<h3 id="profiling-real-world-benchmarks-and-micro-optimi">Profiling, real-world benchmarks, and micro-optimizations<a href="#profiling-real-world-benchmarks-and-micro-optimi">#</a></h3>
<p>So I switched to performance work: I wrote some new tools for the agents to use, a simple profiler and a scraper that built a dataset of 100k popular webpages for real-world benchmarking. I managed to get the speed down below the target with Python micro-optimizations, but only when using the just-released Gemini 3 Pro (which is incredible) to run the benchmark and profiler iteratively. No other model made any progress on the benchmarks.</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">_append_text_chunk</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">chunk</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">ends_with_cr</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">chunk</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ignore_lf</span> <span class="o">=</span> <span class="n">ends_with_cr</span>
<span class="k">return</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore_lf</span><span class="p">:</span>
<span class="k">if</span> <span class="n">chunk</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">:</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="n">chunk</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="c1"># ...</span>
</pre></div>
<h3 id="deleting-untested-code-coverage-as-a-scalpel">Deleting untested code (coverage as a scalpel)<a href="#deleting-untested-code-coverage-as-a-scalpel">#</a></h3>
<p>Later, on a whim I ran <a href="https://coverage.readthedocs.io/"><code>coverage</code></a> on the codebase and found that large parts of the code were "untested". But this was backwards, because I already knew that the tests were covering everything important. So lines with no test coverage could be removed! I told the agent to start removing code to reach 100% test coverage, which was an interesting reversal of roles. These removals actually sped up the code as much as the microoptimizations.</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="c1"># Before: 786 lines of treebuilder code</span>
<span class="c1"># After: 453 lines of treebuilder code</span>
<span class="c1"># Result: Faster and cleaner</span>
</pre></div>
<h3 id="fuzzing-to-find-crashes-and-harden-the-parser">Fuzzing to find crashes and harden the parser<a href="#fuzzing-to-find-crashes-and-harden-the-parser">#</a></h3>
<p>After removing code, I got worried that I had removed too much and missed corner cases. So I asked the agent to write a <a href="https://github.com/EmilStenstrom/justhtml/blob/master/benchmarks/fuzz.py">html5 fuzzer</a> that tried really hard to generate HTML that broke the parser.</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">generate_fuzzed_html</span><span class="p">():</span>
<span class="w"> </span><span class="sd">"""Generate a complete fuzzed HTML document."""</span>
<span class="n">parts</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="o"><</span> <span class="mf">0.5</span><span class="p">:</span>
<span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fuzz_doctype</span><span class="p">())</span>
<span class="c1"># Generate random mix of elements</span>
<span class="n">num_elements</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
<p>It did break the parser, and for each breaking case I asked it to fix it, and write a new test for the test suite. Passed 3 million generated webpages without any crashes, and hardened the codebase again.</p>
<h3 id="comparing-against-other-parsers-how-rare-100-is">Comparing against other parsers (how rare 100% is)<a href="#comparing-against-other-parsers-how-rare-100-is">#</a></h3>
<p>To sanity-check where 100% landed, I ran the <code>html5lib</code> tests against the other parsers. I found that <strong>no other parser passes 90% coverage</strong>, and that <code>lxml</code>, one of the most popular Python parsers, is at <strong>1%</strong>. The reference implementation, html5lib itself, is at 88%. Maybe this is a hard problem after all?</p>
<h3 id="shipping-it-as-a-library-ci-releases-selector-a">Shipping it as a library (CI, releases, selector API)<a href="#shipping-it-as-a-library-ci-releases-selector-a">#</a></h3>
<p>Finally, to make this a good library I asked the agent to set up CI, releases via GitHub, a <a href="https://github.com/EmilStenstrom/justhtml/blob/master/src/justhtml/selector.py">query API</a>, write READMEs, and so on.</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">justhtml</span><span class="w"> </span><span class="kn">import</span> <span class="n">JustHTML</span><span class="p">,</span> <span class="n">query</span>
<span class="n">doc</span> <span class="o">=</span> <span class="n">JustHTML</span><span class="p">(</span><span class="s2">"<div><p>Hello</p></div>"</span><span class="p">)</span>
<span class="n">elements</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="s2">"div > p"</span><span class="p">)</span>
</pre></div>
<p>Decided to rename the library from turbohtml to justhtml, to not fool anyone that it's the fastest library, and instead focus on the feeling of everything just working.</p>
<h2 id="what-the-agent-did-vs-what-i-did">What the agent did vs. what I did<a href="#what-the-agent-did-vs-what-i-did">#</a></h2>
<p>After writing the parser, I still don't know HTML5 properly. The agent wrote it for me. I guided it when it came to API design and corrected bad decisions at the high level, but it did ALL of the gruntwork and wrote all of the code.</p>
<p>I handled all git commits myself, reviewing code as it went in. I didn't understand all the algorithmic choices, but I understood when it didn't do the right thing.</p>
<p>As models have gotten better, I've seen steady increases in test coverage. <strong>Gemini is the smartest model from a one-shot perspective, while Claude Opus is best at iterating its way to a good solution.</strong></p>
<h2 id="practical-tips-for-working-with-coding-agents">Practical tips for working with coding agents<a href="#practical-tips-for-working-with-coding-agents">#</a></h2>
<ol>
<li><strong>Start with a clear, measurable goal.</strong> "Make the tests pass" is better than "improve the code."</li>
<li><strong>Review the changes.</strong> The agent writes a lot of code. Read it. You'll catch issues and learn things.</li>
<li><strong>Push back.</strong> If something feels wrong, say so. "I don't like that" is a valid response.</li>
<li><strong>Use version control.</strong> If the agent goes in the wrong direction, you can always revert.</li>
<li><strong>Let it fail.</strong> Running a command that fails teaches the agent something. Don't try to prevent all errors upfront.</li>
</ol>
<h2 id="was-it-worth-it-and-what-quickly-meant">Was it worth it (and what “quickly” meant)?<a href="#was-it-worth-it-and-what-quickly-meant">#</a></h2>
<p>Yes. <a href="https://github.com/EmilStenstrom/justhtml">JustHTML</a> is about 3,000 lines of Python with 8,500+ tests passing. I couldn't have written it this quickly without the agent.</p>
<p>But "quickly" doesn't mean "without thinking." I spent a lot of time reviewing code, making design decisions, and steering the agent in the right direction. The agent did the typing; I did the thinking.</p>
<p>That's probably the right division of labor.</p>
3 tips for agile roadmaps2023-05-18T18:17:00+02:002023-05-18T18:17:00+02:00http://friendlybit.com/product/agile-roadmaps/Emil Stenström"Roadmapping is anti-agile. Instead, we should only have priorities."This was a response to my product roadmaps article - discuss! Are roadmaps anti-agile?—...
<blockquote class="twitter-tweet" data-dnt="true"><p lang="en" dir="ltr">"Roadmapping is anti-agile. Instead, we should only have priorities."<br><br>This was a response to my product roadmaps article - discuss! <br><br>Are roadmaps anti-agile?</p>— Ant Murphy (@ant_murphy) <a href="https://twitter.com/ant_murphy/status/1658955594177421312?ref_src=twsrc%5Etfw">May 17, 2023</a></blockquote>
<p>My response: Product Roadmaps can be agile or not, it depends on how you use them.</p>
<p>The idea behind a roadmap is to deliver predictability to the business, but how does that work with also being able to respond to changes?</p>
<h2 id="1-update-it-regularly">1. Update it regularly<a href="#1-update-it-regularly">#</a></h2>
<p>Once a year is too slow, and leaves no wiggle room for new insights or priorities throughout the year. But updating it too often makes it hard to use instead. I've seen quarterly updates work well for a 50 people company. Shorter for a smaller or younger company, longer for a bigger or more slow moving one.</p>
<h2 id="2-schedule-broad-areasproblems-not-features">2. Schedule broad areas/problems, not features<a href="#2-schedule-broad-areasproblems-not-features">#</a></h2>
<p>Features change more often than problems, so putting problem areas in the roadmap works better for both delivering some predictability and leaving space for learning. The clearer you can be with what effect you are looking for, the more empowered the team can be in solving the problem.</p>
<h2 id="3-dont-make-everything-time-bound">3. Don’t make everything time bound<a href="#3-dont-make-everything-time-bound">#</a></h2>
<p>If every item in the roadmap is time bound, then updating it regularly will be though. Put a time frame on the nearest items, that you know more about, so the business can plan. But don't worry about the ones longer in the future.</p>
<p>That's it, three quick tips to work with agile roadmaps. Sounds easy? It's not.</p>
How to prioritize a feature list, the hard way2023-06-08T07:53:00+02:002023-06-08T07:53:00+02:00http://friendlybit.com/product/customer-feedback/Emil StenströmWhat % of the top 10 [features that customers ask for] do you end up implementing typically?— Jason Cohen (@asmartbear) June 7, 2022 Raw customer feedback...
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">What % of the top 10 [features that customers ask for] do you end up implementing typically?</p>— Jason Cohen (@asmartbear) <a href="https://twitter.com/asmartbear/status/1534193998843330568?ref_src=twsrc%5Etfw">June 7, 2022</a></blockquote>
<p>Raw customer feedback is always too much about features, and too little about the problems customers are trying to solve.</p>
<p>So you need to rework the feedback to map to the problems customers have instead, merging and splitting feedback as you go. Hard work. Now you have transformed your list of features to a list of problems.</p>
<p>Can’t you just build things in this list in “most common problems” order? No. Because how often a problem occurs is not the same as how important it is.</p>
<p>Also, the <em>type of user</em> that has that problem is also very important.</p>
<p>In a B2B context, the buyer is much more important than the user. In B2C there are different kinds of users, which have wildly different priority.</p>
<p>And there are likely five other important factors too, all specific to your specific problem area, that we haven't even talked about yet.</p>
<p>Could you build a ranking system weighing these things together, and get a bottom up priority list?</p>
<p>You could, but it wouldn’t be at all as exact as it looks to be. It’s easy to fool yourself. Remember that the raw customer was very biased, is this something to build a solid mathematical model based on? I think not.</p>
<p>A better way is to not build a ranking model, and work from the list of common customer problems.</p>
<p>Instead, look at your company’s business goals, and start mapping customer problems to business goals.</p>
<p>Say some users have problems with the checkout flow. This maps directly to a revenue target.</p>
<p>Someone didn’t like the design of the site. Talking to them, you find that that leads to them not trusting you. Which indirectly leads to lost sales.</p>
<p>So maybe you put up “Increase customer trust” as a node in a tree and continue mapping. As you add more feedback, and more nodes, you get a much better picture of how things fit together.</p>
<p>Looking at the whole tree, you can now prioritize which customer problems to work on, based on business goal priority. This will make a lot more sense.</p>
<p>Because your job is not to build features, or even to solve customer problems. It’s to drive business outcomes.</p>
<p>And yes, you do that by solving customer problems, and building features. But that’s not where you start.</p>
<p>That’s how you prioritize a feature list, the hard way.</p>
The case for national digital currencies, not Bitcoin2021-06-09T10:06:00+02:002021-06-09T10:06:00+02:00http://friendlybit.com/future/the-case-for-national-digital-currencies-not-bitcoin/Emil StenströmBitcoin is now accepted as legal tender in El Salvador. Many believe all countries should do the same, and that the time is right for Bitcoin to take over...
<p>Bitcoin is now <a href="https://www.bbc.com/news/world-latin-america-57373058">accepted as legal tender in El Salvador</a>. Many believe all countries should do the same, and that the time is right for Bitcoin to take over the world as a <strong>global digital currency</strong>.</p>
<h2 id="decentralization-is-not-a-good-idea-for-a-currency">Decentralization is not a good idea for a currency<a href="#decentralization-is-not-a-good-idea-for-a-currency">#</a></h2>
<p>The core tenet of most cryptocurrencies is <em>decentralization</em>, the idea that no single entity or individual should have absolute control over it. Instead it's protected by the fact that controlling 51% of the network is hard when lots of diverse entities are involved. The push for decentralization in cryptocurrencies is the root of most of its problems.</p>
<ol>
<li>For the 51% protection to work you need a large network of independent server operators</li>
<li>To get that you need to give them some incentive to host their servers</li>
<li>It's natural then, to give them some of the new currency in return</li>
<li>But the currency is worth zero when no one is using it...</li>
<li>So everyone who joins early, bets that the value will <em>not</em> be stable, but grow exponentially over time</li>
</ol>
<p>This is not the recipe for how to construct something that should be stable, and be used as a digital currency.</p>
<p>Instead we should <strong>skip the decentralization part</strong>, and have a central bank guarantee the value. This makes it stable, and stable is something we definitely need for a currency.</p>
<h2 id="proof-of-work-makes-things-worse">Proof of work makes things worse<a href="#proof-of-work-makes-things-worse">#</a></h2>
<p>To get any value from a cryptocurrency you need to limit supply somehow, if there was infinite money, it wouldn't be worth anything. For Bitcoin, this is done by requiring each server to randomly try solutions to a tricky algorithmic problem. Solving it gives you coins.</p>
<p>Proof of work for Bitcoin is a colossal waste of electricity. Especially in countries where electricity is generated by <a href="https://medium.com/crypto-lucid/enough-with-bitcoins-greenwashing-bitcoin-uses-mainly-fossil-energy-b83256d693bc">non-clean energy sources</a>. But even for renewables, is this really the best way to use our limited energy? Let's charge car batteries, construct fossil free steel, and capture CO<sub>2</sub> from the atmosphere with that electricity instead.</p>
<p>There are other ways to limit supply in other cryptocurrencies, like proof of stake, and I agree that these would be better for a currency. But the easiest solution is to <strong>let a central bank guarantee the value</strong>, and avoid the need for a "proof of X" system at all.</p>
<h2 id="ease-of-use-for-crime-is-not-a-good-feature">Ease of use for crime is not a good feature<a href="#ease-of-use-for-crime-is-not-a-good-feature">#</a></h2>
<p>There is a reason crime groups love Bitcoin: Transactions are anonymous. All you need is a Bitcoin address to send money to. This means no taxation, as transactions are not tied to any individual. It also means that cyber criminals just need to transfer all proceeds from a hack to their own accounts, no need to hide things further.</p>
<p>When crime groups get the same access to capital as everyone else they can do more damage. I hope you agree that this is something we should try to limit. But this is not something that cryptocurrencies can do, because it requires a centralized authority that can act on suspicion of wrongdoing. We already have that system in place in our governments, it's just that cryptocurrencies are not built with stopping crime in mind. <strong>A new digital currency should take crime into consideration</strong>.</p>
<p>Of course, accessing your transactions should require reasonable cause as decided by a judge, and be protected by strict privacy laws. <a href="https://www.courthousenews.com/banks-profit-from-selling-your-spending-data/">Probably better protected than your bank statement is today</a>.</p>
<h2 id="another-look-at-the-el-salvador-use-of-bitcoin">Another look at the El Salvador use of Bitcoin<a href="#another-look-at-the-el-salvador-use-of-bitcoin">#</a></h2>
<p>When you <a href="https://www.coindesk.com/its-official-el-salvadors-legislature-votes-to-adopt-bitcoin-as-legal-tender">look closer at how El Salvador plans to use Bitcoin</a> a couple of things stand out:</p>
<ul>
<li>20% of El Salvador's GDP is people sending money to relatives, and they want to encourage that</li>
<li>All merchants will be mandated to accept Bitcoin as payment</li>
<li>The government will accept the monetary risk of merchants by directly converting Bitcoin to US dollars (their native currency)</li>
<li>There's a trust fund with $150 million to balance the risk</li>
<li>They will continuously sell off Bitcoin to balance the trust fund</li>
<li>There is talk of the state promoting bitcoin mining</li>
</ul>
<p>This is not something other countries should try to emulate:</p>
<ol>
<li>Tying a country's finances to a volatile security like Bitcoin is a very high risk move. If the Bitcoin price where to crash, all the Bitcoin the government holds would be worthless. It could also rise, but this is nothing but reckless.</li>
<li>Receiving money from relatives requires their relatives to accept the risk of holding Bitcoin. If you buy Bitcoin one day, it might be worth half what you bought it for the day after. The government will not mitigate that risk.</li>
<li>The tech to accept Bitcoin might not be readily available to everyone, especially a poor country like El Salvador.</li>
<li>As previously stated, betting on Bitcoin is not environmentally sound.</li>
</ol>
<h2 id="requirements-for-an-ideal-digital-currency">Requirements for an ideal digital currency<a href="#requirements-for-an-ideal-digital-currency">#</a></h2>
<p>So let's sum up what I've talked about so far, in terms of what I believe are requirements for a digital currency.</p>
<ul>
<li>It should be stable, so it can be used for day-to-day transactions</li>
<li>Environmental impact of running the system should be low</li>
<li>Law enforcement should be able to access to transaction data when warranted</li>
</ul>
<p>Let's add some things that Bitcoin is doing well:</p>
<ul>
<li>It should be available to anyone</li>
<li>There should be a digital wallet that it's easy to send money to</li>
<li>Transaction costs should be low, or even zero</li>
</ul>
<p>Let's see if we can build a system that would satisfy all six requirements above, fully or partially.</p>
<h2 id="a-national-digital-currency">A national digital currency<a href="#a-national-digital-currency">#</a></h2>
<p>Each country should have their own digital currency, backed by that country's central bank. The digital money would be considered the same as paper money, and the central bank would be in control of minting new digital money, just like they are with paper money today.</p>
<p>They don't need a blockchain system for this, as there <em>is</em> trust in this system. So no proof of work, and no server farms. A simple database with a transaction ledger would be fine. Of course it needs to be protected like a bank's IT system would. This makes sure we're operating with low environmental impact.</p>
<p>A new government agency would be created whose job it would be to safeguard the transaction ledger in a privacy sensitive way. The agency should have strict rules for when transaction data can be disclosed to law enforcement and not. I believe separating responsibility like this would be an effective way to make sure there is better balance between the needs of law enforcement and privacy.</p>
<p>Every citizen should get a digital wallet from the government based on their social security number (or equivalent) or registered company ID. This account could be used for government payouts instead of other bank accounts. Ideally there should be a way to easily add accounts for people that live outside the system (paperless, immigrants living in the country, ...), so that these digital accounts really could be used by everyone.</p>
<p>There should be a basic interface supplied by the government for making payments, but also an API so private organizations could build other payment solutions using these digital wallets. Transaction costs should be low or zero when done through the government supplied interface, but third parties could add fees when doing transactions through the API. Allowing fees and an API ensures that there are ways for commercial companies to improve the payment flow in interesting ways.</p>
<h2 id="in-summary">In summary<a href="#in-summary">#</a></h2>
<p>I think a setup like this would be great for simplifying digital commerce in a country. It would expand access to digital services, open plentiful of new use-cases, and decrease the cost of making digital transactions.</p>
<p>Luckily, it seems at least <a href="https://twitter.com/lagarde/status/1382991097849376768">80 central banks are exploring this use-case</a>. Let's hope we see more action, and less talk.</p>
[The Listserve] How randomness affects your life2017-12-02T12:04:00+01:002017-12-02T12:04:00+01:00http://friendlybit.com/life/the-listserve-how-randomness-affects-your-life/Emil StenströmIt's a mistake not to think about randomness, for randomness is what you get if you don't make choices. Do you really want randomness controlling the most...
<p>It's a mistake not to think about randomness, for randomness is what you get if you don't make choices. Do you really want randomness controlling the most important events in your life?</p>
<p>There are two kinds of randomness: The "true" kind, where it's impossible, using the science we know, to know the outcome. Maybe you've heard about the <a href="https://en.wikipedia.org/wiki/Uncertainty_principle">Heisenberg's uncertainty principle</a>. It says that, in some circumstances, if we try to measure, we destroy the thing we wanted to measure. It's not measurable, we don't know, therefor it's random. This is a basic thing in nature, a randomness we can't change no matter how hard we try.</p>
<p>Then there's the more common kind. The kind that SEEMS random to us. If we throw a die, and three comes up, was that randomness? Not really, because if we could throw the die in exactly the same way, the same number would come up. That's not how real randomness works, but it's the kind of random we surround ourself with every day. Let's focus on this kind of every-day randomness.</p>
<p>Is there any way to control randomness? Yes! You can reduce uncertainty. Example: Say you want to meet a partner, something that is seemingly random (we've all hear the stories of how people "randomly" bumped into each other). Is there something you can do to make that more likely (i.e. less random)? Maybe you could hang out in places where a good partner is likely to hang out? Probably not in your livingroom right? At a local bar? At an evening course in pottery? Think about it. This is you consciously reducing the amount of randomness around meeting someone.</p>
<p>So while randomness is something that affects us all, you can affect it by just knowing more, and adapting. Now, knowing this, is there some area of your life that you find extra important? Is there something that you really would miss if it got lost on you? Maybe it's time to reduce the uncertainty and randomness around that thing? Is there something you could do right now?</p>
<p><strong>My point: Don't let randomness control what happens to the most important parts of your life. If you don't do anything, it will.</strong></p>
How to make e-mail encrypted for everyone2016-10-28T23:26:00+02:002016-10-28T23:26:00+02:00http://friendlybit.com/security/how-to-make-e-mail-encrypted-for-everyone/Emil StenströmUpdate: For a wholesome look at e-mail security this video from the CTO of ProtonMail: https://vimeo.com/216747532 When you send an e-mail today it's sent...
<blockquote>
<p><strong>Update</strong>: For a wholesome look at e-mail security this video from the CTO of ProtonMail: <a href="https://vimeo.com/216747532">https://vimeo.com/216747532</a></p>
</blockquote>
<p>When you send an e-mail today it's sent in plaintext. This means that when you connect to your local coffee shop's WiFi they can intercept all e-mail that is sent through their router. This is probably not the relationship you have with your barista…</p>
<p>E-mail is way more important than this, and should receive the same privacy protection as the web has with HTTPS. I haven't seen any meaningful progress on e-mail encryption in a long time, so this article is a suggestion of how to get things moving.</p>
<p>The base idea is this: <strong>We should make e-mail work just like the web in terms on encryption</strong>:</p>
<ul>
<li>Encryption should be added gradually, without breaking backwards compatibility (interoperability)</li>
<li>Intermediate servers shouldn't be able to read the message (privacy)</li>
<li>Users should be able to keep sending and receiving e-mail like they always have (usability)</li>
<li>E-mail clients and e-mail providers should be able to easily implement the scheme (simplicity)</li>
</ul>
<h2 id="encrypt-as-much-as-possible-of-the-e-mail-message">Encrypt as much as possible of the e-mail message<a href="#encrypt-as-much-as-possible-of-the-e-mail-message">#</a></h2>
<p>For web traffic, we've encrypting everything <a href="https://idea.popcount.org/2012-06-16-dissecting-ssl-handshake/">except the domain name</a> of the site we're connecting to, this is how e-mail should work too. Since we need to know who to send the e-mail to, we should encrypt everything except the recipient address.</p>
<p>Some of you might have read about <a href="https://en.wikipedia.org/wiki/Opportunistic_TLS">STARTTLS</a>, a way to make SMTP encrypted. Unfortunately STARTTLS has <a href="https://blog.filippo.io/the-sad-state-of-smtp-encryption/">several problems</a> that makes it unfit to solve the privacy problem:</p>
<ul>
<li>It only encrypts the message <strong>between</strong> the many servers your e-mail passes through. Your e-mail is decrypted and exists in plaintext on each of the intermediate servers. If any of the intermediate servers is hacked they get full access to all e-mails passing through. You likely don't have that kind of relationship with your ISP network administrator either…</li>
<li>If any of the intermediate servers doesn't support STARTTLS, the connection is downgraded to plaintext instead. One old server and the whole chain breaks.</li>
</ul>
<p>We should apply encryption on the client when sending, and decrypt at the recipient. No intermediate servers should get access to the message.</p>
<h2 id="encrypt-with-public-key-cryptography-without-the">Encrypt with public-key cryptography (without the hassle)<a href="#encrypt-with-public-key-cryptography-without-the">#</a></h2>
<p>The best way to handle this encryption is with <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>, where the sender first fetches the public key of the receiver, sends the message encrypted with that key, and then that the receiver decrypts it using their private key.</p>
<p>People are already sending e-mail this way with <a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">PGP</a>, so way not just use this everywhere? It has several big usability problems:</p>
<ul>
<li><strong>You need to do key management yourself</strong>. On the web the browser handles all cryptography for you. You type the address in the browser and everything just works. This is not the case with PGP. Look at this guide in the eyes of a normal person: <a href="http://zacharyvoase.com/2009/08/20/openpgp/">OpenPGP for a complete beginner</a> - it quickly goes into downloading zipfiles, package managers and using the command line to generate keys.</li>
<li><strong>You need to install software on your computer</strong>. Most e-mail providers are moving to the web, having to install a browser plugin just to send e-mail is not the experience we should strive for. I understand that this is means your e-mail provider can read your e-mail, so it won't work for everyone. But I think most people will accept that the same way they accept that their bank can read their bank statement. If we can trade this for usability it's still a HUGE step up for privacy.</li>
</ul>
<p>Here's how this could be done differently:</p>
<p><strong>Encryption:</strong></p>
<ol>
<li>For each recipient in the To, Cc, and Bcc fields:<ol>
<li>Do a lookup against their domain to see if it supports encryption. This should be a new DNS record that points to an address that the e-mail client can use to fetch the public key for a specific user of that domain.</li>
<li>Fetch the public key for each of the users of the domain</li>
<li>If both the domain has encryption support and the public key can be fetched, show a lock symbol beside that e-mail address to show that the message to that recipient will be encrypted. Clicking the lock can show information about the encryption that will be used, just like browsers do today.</li>
</ol>
</li>
<li>When the message is sent, split it into as many parts as the number of recipients and encrypt each part with that recipient's public key. Send it off to each recipient using the normal protocols. Users on domains that don't support encryption will get messages sent in plaintext, just like today. This ensures support can be added gradually.</li>
</ol>
<p>Note that for the user nothing changes compared to how they send e-mail today, except that the lock shows up. Web users are slowly learning about the importance of the lock symbol when browsing the web, transfering that knowledge to e-mail too will create a push for e-mail server operators to support encryption.</p>
<p><strong>Decryption:</strong></p>
<ul>
<li>When the encrypted e-mail reaches the intended recipients e-mail server, that server uses the private key for that user to decrypt the message and (securely) deliver it the the users inbox. The user reads their e-mail like they've always have.</li>
</ul>
<p>Some may frown reading that I suggest leaving the private key in the hands of your e-mail provider. I agree that this means you lose some privacy to your e-mail provider. The upside here is that we gain a lot of usability. An e-mail provider (such as Gmail) could and an e-mail client (such as Thunderbird) could update all their software tomorrow and <strong>all e-mail sent from Thunderbird to Gmail would be instantly encrypted</strong>. This removes the burden of normal users to learn about cryptography to be safe on the web.</p>
<p>In summary, these are the changes that needs to happen for e-mail move towards being encrypted by default:</p>
<h2 id="consequences-for-e-mail-clients">Consequences for e-mail clients<a href="#consequences-for-e-mail-clients">#</a></h2>
<ul>
<li><strong>New features needed:</strong><ul>
<li>Fetch a DNS record for each receiving domain they want to send an e-mail to</li>
<li>Fetch each receiving user's public key in the background</li>
<li>And encrypt as much as possible of the outgoing e-mail</li>
<li>Send the e-mail using the normal protocols</li>
</ul>
</li>
<li><strong>Ways to pitch this to users:</strong><ul>
<li>All e-mail sent to e-mail providers that support this scheme will be encrypted by default, with no effort on your part</li>
<li>You can easily see which addresses get encrypted messages with the lock icon that you know from browsers</li>
<li>Increased privacy from prying eyes</li>
</ul>
</li>
</ul>
<h2 id="consequences-for-e-mail-providers">Consequences for e-mail providers<a href="#consequences-for-e-mail-providers">#</a></h2>
<ul>
<li><strong>New features needed:</strong><ul>
<li>Add a DNS record that points to their public keys</li>
<li>Serve the public key of a specific user that the e-mail clients ask for</li>
<li>Decrypt incoming e-mails using the private key of that user</li>
<li>Deliver the e-mail using the normal protocols</li>
</ul>
</li>
<li><strong>Ways to pitch this to users:</strong><ul>
<li>All e-mails sent from clients that support this scheme will be encrypted by default, with no effort on your part</li>
<li>Increased privacy from prying eyes, do you really trust your local coffee shop as much as your e-mail provider?</li>
</ul>
</li>
<li><strong>Business reasons:</strong><ul>
<li>Support privacy without letting go of the chance to serve ads based on the content of the users e-mails. This is a very important point for big players like Gmail that serve ads. Users or course still have the option to use another e-mail provider or add PGP if they want.</li>
<li>Nothing in this scheme blocks smaller players from making their users safe using the same methods as the big players will.</li>
</ul>
</li>
</ul>
<h2 id="in-summary">In summary<a href="#in-summary">#</a></h2>
<p>I think this is a very straightforward way to make all e-mail encrypted. If anyone has a better suggestion that balances the needs of users, e-mail clients and e-mail providers differently I'm all ears. But let's not let this privacy travesty go on much longer…</p>
Hur säkra är svenska banker? (Swedish)2015-03-01T19:22:05+01:002015-03-01T19:22:05+01:00http://friendlybit.com/security/hur-sakra-ar-svenska-banker/Emil StenströmSäkerheten varierar stort bland svenska banker. Bankens storlek hänger inte ihop med hur väl dom hanterar säkerheten. Ingen av de fyra storbankerna kom med...
<p><em>Säkerheten varierar stort bland svenska banker. Bankens storlek hänger inte ihop med hur väl dom hanterar säkerheten. Ingen av de fyra storbankerna kom med på topplistan. Några små banker finns med i toppen, några riktigt stora finns i botten.</em></p>
<p>För att testa bankernas säkerhet gav jag varje bank två olika betyg:</p>
<ol>
<li><p><strong>Kryptering: Krypteras trafiken mellan dig och banken ordentligt?</strong></p>
<p>Utan kryptering kan andra se de uppgifter som du skickar till banken, personnummer, lösenord, och koder. Dessa relativt tekniska tester görs med hjälp av <a href="https://www.ssllabs.com/ssltest/">SSL Labs</a>. Betygsskalan kommer direkt från SSL Labs och går från A-F, där A är bäst. Notera att jag testar inloggningssidan, inte startsidan.</p>
</li>
<li><p><strong>Visuellt: Ser allt ok ut i webbläsaren?</strong></p>
<p>Det finns gott om guider som lär ut webbsäkerhet till ovana användare. Här tittar jag på om banksajterna är konfigurerade så att allt ser OK ut för en vanlig användare. Har sajten grönt hänglås? Jag har använt samma betygsskala: A-F, där A är bäst.</p>
</li>
</ol>
<p>Bankerna kommer från Finansinspektionens lista över <a href="http://www.fi.se/Templates/InstitutcategoriesPage.aspx?id=2466?la=sv">bankaktiebolag och medlemsbanker</a>. De lokala sparbankerna har inte tagits med, och inte heller de som främst riktar sig till företag. Testet gjordes 2015-02-28. <a href="https://docs.google.com/spreadsheets/d/1KBwhyUt9Afo7_4p0izS8eSudGyHr89Ckwym--pNe1S4/edit?usp=sharing">Rådata för testet finns här</a>, inklusive länkarna till SSL Labs där du kan se testresultatet själv.</p>
<h3 id="uppdaterat">Uppdaterat:<a href="#uppdaterat">#</a></h3>
<p>Eftersom denna artikel fått väldigt bra spridning har flera av bankerna hört av sig. Ofta med konkreta förbättringar de har genomfört på grund av min artikel. Här hittar du en tidslinje över hur artikeln har ändrats över tid.</p>
<ul>
<li>2015-03-03: <strong>Inga fler uppdateringar görs från detta datum och framåt...</strong></li>
<li>2015-03-02: <strong>Danske Bank</strong> tillagd. Dom får tyvärr bara ett C.</li>
<li>2015-03-02: Kontrollerade stöd för <a href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions"><strong>DNSSEC</strong></a>: Landshypotek, Marginalen, Danske Bank, och Länsförsäkringar är de enda som stödjer det.</li>
<li>2015-03-03: Rättade felaktig klassificering av SBAB. Jag hade testat startsidans certifikat, inte inloggningssidans.</li>
<li>2015-03-04: <strong>SBAB Bank</strong> har förbättrat sitt certifikat på startsidan.</li>
<li>2015-03-04: <strong>Länsförsäkringar</strong> har uppdaterat sitt certifik och får nu ett B.</li>
<li>2015-03-05: <strong>Ekobanken</strong> har uppdaterat sitt certifikat och får nu ett A.</li>
<li>2015-03-05: <strong>Forex bank</strong> har uppdaterat sitt certifikat och får nu ett A.</li>
<li>2015-03-05: <strong>Santander Consumer</strong> har släppt en ny internetbank och hamnar nu på B.</li>
<li>2015-03-06: <strong>MedMera Bank</strong> har uppdaterat sitt certifikat och får nu ett B.</li>
<li>2015-03-07: <strong>Carnegie Bank</strong> har uppdaterat sitt certifikat och får nu ett A</li>
<li>2015-03-08: <strong>SBAB Bank</strong> har gjort ytterligare uppdateringar och blir första bank med A/A. Full pott!</li>
<li>2015-03-12: <strong>JAK Medlemsbank</strong> har uppdaterat sitt certifikat och får nu ett B.</li>
<li>2015-03-12: <strong>Länsförsäkringar</strong> har uppdaterat sitt certifikat och får nu ett A-.</li>
<li>2015-03-18: <strong>Swedbank</strong> kör nu HTTPS på sin startsida.</li>
<li>2015-04-11: <strong>Resurs Bank</strong> har uppdaterat certifikatet på sin startsida, och kräver nu även https där. Inloggningscertifikatet kommer att uppdateras också, men är inte klart ännu.</li>
<li>2015-04-24: <strong>Skandiabanken</strong> kör nu HTTPS på sin startsida.</li>
<li>2015-10-28: <strong>Resurs Bank</strong> har flyttat sin inloggningssida till egen domän och certifikat.</li>
</ul>
<h2 id="bankerna-med-bast-sakerhet-a">Bankerna med bäst säkerhet (A):<a href="#bankerna-med-bast-sakerhet-a">#</a></h2>
<p>Fantastiska resultat för alla dessa fyra banker. Krypteringen uppfyller best practices och du kan sova gott med vissheten att din bank är bland Sveriges bästa.</p>
<table>
<tr>
<th rowspan="2">
</th>
<th colspan="2">
Kryptering
</th>
<th colspan="2">
Visuellt
</th>
</tr>
<tr>
<th>
Betyg
</th>
<th>
Not
</th>
<th>
Betyg
</th>
<th>
Not
</th>
</tr>
<tr>
<td>
<strong>SBAB</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
1
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Skandiabanken</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
1
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Resurs Bank</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
1
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Landshypotek</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
2
</td>
<td>
<strong>B</strong>
</td>
<td>
4
</td>
</tr>
<tr>
<td>
<strong>Carnegie Investment Bank</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
4
</td>
</tr>
<tr>
<td>
<strong>Ekobanken</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
4
</td>
</tr>
<tr>
<td>
<strong>Forex Bank</strong>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
4
</td>
</tr>
<tr>
<td>
<strong>Länsförsäkringar Bank</strong>
</td>
<td>
<strong>A-</strong>
</td>
<td>
3
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Marginalen Bank</strong>
</td>
<td>
<strong>A-</strong>
</td>
<td>
3
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Nordnet</strong>
</td>
<td>
<strong>A-</strong>
</td>
<td>
3
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
</table>
<p><strong>Noter</strong>:</p>
<ol>
<li>Grattis till <strong>SBAB Bank, Skandiabanken</strong> och <strong>Resurs Bank</strong> som får A i båda kategorier.</li>
<li>En extra eloge till <strong>Landshypotek</strong> som får noll varningar från SSL Labs.</li>
<li>Flera banker får <strong>A minus</strong> eftersom de saknar stöd för <a href="https://en.wikipedia.org/wiki/Forward_secrecy">Forward Secrecy</a>. Förenklat innebär det att krypteringsmetoden ändras över tid, så att någon som avlyssnat trafik till en sajt för länge sedan inte kan dekrypteras den om sajten hackas senare. Totalt har endast tre svenska banker har stöd för detta (Landshypotek, Skandiabanken och ICA Banken (se nedan)). Bra jobbat!</li>
<li>Flera bankers <strong>startsidor saknar kryptering</strong>. Eftersom inloggningssidorna är krypterade är detta inte katastrof, bara olyckligt. Att ha kryptering på hela sin webbplats är en bra idé eftersom kunden vänjer sig vid att se det <a href="https://support.google.com/chromebook/answer/95617">gröna hänglåset</a> så länge dom har med banken att göra.</li>
</ol>
<h2 id="bankerna-som-nastan-kom-med-pa-topplistan-b">Bankerna som nästan kom med på topplistan (B):<a href="#bankerna-som-nastan-kom-med-pa-topplistan-b">#</a></h2>
<p>Även här får bankerna bra betyg. Anledningen att dom missar topplistan är att samtliga banker i denna lista har problem med vilka krypteringsalgoritmer/protokoll dom stödjer. Det är enkelt egentligen: Om en krypteringsmetod är bevisat osäker (t.ex. RC4 eller SSL3) ska den plockas bort. Att ha den kvar innebär att kunderna luras att tro att deras uppkoppling mot banken är säker trots att den inte är det.</p>
<table>
<tr>
<th rowspan="2">
</th>
<th colspan="2">
Kryptering
</th>
<th colspan="2">
Visuellt
</th>
</tr>
<tr>
<th>
Betyg
</th>
<th>
Not
</th>
<th>
Betyg
</th>
<th>
Not
</th>
</tr>
<tr>
<td>
<strong>ICA Banken</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
1
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Avanza</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>MedMera Bank</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Santander Consumer</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>JAK Medlemsbank</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>Swedbank</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>A</strong>
</td>
<td>
</td>
</tr>
<tr>
<td>
<strong>SEB</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
2
</td>
</tr>
<tr>
<td>
<strong>Volvofinans Bank</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
2
</td>
</tr>
<tr>
<td>
<strong>Ikanobanken</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
2
</td>
</tr>
<tr>
<td>
<strong>Nordea Bank AB</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
2
</td>
</tr>
<tr>
<td>
<strong>Handelsbanken</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>B</strong>
</td>
<td>
2
</td>
</tr>
</table>
<p><strong>Noter</strong>:</p>
<ol>
<li><strong>ICA Banken</strong> är nästan med i topplistan ovan. Dom krypterar sin startsida, dom stödjer <a href="https://en.wikipedia.org/wiki/Forward_secrecy">Forward Secrecy</a>, och är dessutom den enda bank som stödjer <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HTTP Strict Transfer Security</a>. Tyvärr används krypteringsalgoritmen <a href="https://en.wikipedia.org/wiki/RC4#Security">RC4</a>, en algoritm som inte är säker alls. Har du en lite äldre webbläsare kan du alltså bli lurad att allt ser bra ut, trots att trafiken mellan dig och banken relativt enkelt kan avlyssnas. ICA Banken borde helt enkelt stänga av stöd för RC4, be sina användare att uppgradera sin webbläsare, och inta toppositionen i denna lista.</li>
<li>Flera bankers <strong>startsidor saknar kryptering</strong>. Eftersom inloggningssidorna är krypterade är detta inte katastrof, bara olyckligt. Att ha kryptering på hela sin webbplats är en bra idé eftersom kunden vänjer sig vid att se det <a href="https://support.google.com/chromebook/answer/95617">gröna hänglåset</a> så länge dom har med banken att göra.</li>
</ol>
<h2 id="bankerna-som-du-borde-vara-orolig-for-c">Bankerna som du borde vara orolig för (C):<a href="#bankerna-som-du-borde-vara-orolig-for-c">#</a></h2>
<p>Någonstans här är det dags att börja bli orolig. Dessa banker har gemensamt att dom inte hanterar sin kryptering på rätt sätt. Extra olyckligt är det ställt för OK-Q8 Bank som använder en <a href="https://nettbank.edb.com/">färdig produkt från EDB</a> och ändå får sämst betyg av C-bankerna.</p>
<table>
<tr>
<th rowspan="2">
</th>
<th colspan="2">
Kryptering
</th>
<th colspan="2">
Visuellt
</th>
</tr>
<tr>
<th>
Betyg
</th>
<th>
Not
</th>
<th>
Betyg
</th>
<th>
Not
</th>
</tr>
<tr>
<td>
<strong>Danske Bank</strong>
</td>
<td>
<strong>B</strong>
</td>
<td>
</td>
<td>
<strong>F</strong>
</td>
<td>
2
</td>
</tr>
<tr>
<td>
<strong>Erik Penser</strong>
</td>
<td>
<strong>C</strong>
</td>
<td>
3
</td>
<td>
<strong>F</strong>
</td>
<td>
4, 5
</td>
</tr>
<tr>
<td>
<strong>OK-Q8 Bank</strong>
</td>
<td>
<strong>C</strong>
</td>
<td>
3
</td>
<td>
<strong>F</strong>
</td>
<td>
1, 4, 6
</td>
</tr>
</table>
<p><strong>Noter:</strong></p>
<ol>
<li>OK-Q8 Bank lyckas vända något bra - det gröna hänglåset - till något mindre bra. Ett klick på det gröna hänglåset visar vem som garanterar säkerheten på webbplatsen. Bakom OK-Q8 Bank står EVRY AS, <strong>ett norskt bolag, som garant</strong>.Hur ska en kund veta att det är banken som står bakom det certifikatet, att dom har kommit till rätt sajt? Underkänt.</li>
<li>Danske Bank har bara har satsat på en <strong>grått hänglås</strong>. Den gråa hänglåset betyder att uppkopplingen är krypterad, men inte vem som står bakom den (så kallad <a href="https://en.wikipedia.org/wiki/Extended_Validation_Certificate">Extended Validation</a>). För något så känsligt som banktjänster ska ett riktigt EV-certifikat användas.</li>
<li>Flera banker verkar inte ha skyddat sig från ett <strong>säkerhetshål som döpts till <a href="https://community.qualys.com/blogs/securitylabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack">POODLE</a></strong>. Google publicerade detaljer om hur man använder sig av hacket redan i oktober 2014. Att det fortfarande finns banker som inte skyddat sig är anmärkningsvärt.</li>
<li>Flera bankers <strong>startsidor saknar kryptering</strong>. Eftersom inloggningssidorna är krypterade är detta inte katastrof, bara olyckligt. Att ha kryptering på hela sin webbplats är en bra idé eftersom kunden vänjer sig vid att se det <a href="https://support.google.com/chromebook/answer/95617">gröna hänglåset</a> så länge dom har med banken att göra.</li>
<li>Erik Penser gör kapitalfel på sin inloggningssida, den <strong>ser inte ut att vara krypterad</strong>. Som kund ska man aldrig skriva in känsliga inloggningsuppgifter på en webbsida som saknar hänglås. Erik Penser gör visserligen rätt bakom kulisserna (inloggningssidan ÄR krypterad) men det visas inte upp för kunden alls. Gör om, gör rätt.</li>
<li>OK-Q8 Bank och Danske Bank visar inte något som helst hänglås i webbläsaren. Anledningen är att inloggningssidan <strong>hämtar bilder över en helt okrypterad uppkoppling</strong>. Det gör att man väldigt lätt kan se att du loggar in på banken. Danske Bank döljer dessutom denna miss genom att visa inloggningssidan i en popupruta. Riktigt illa.</li>
</ol>
<h2 id="bankerna-du-borde-undvika-f">Bankerna du borde undvika (F):<a href="#bankerna-du-borde-undvika-f">#</a></h2>
<p>Dags för bottennoteringarna. Det gemensamma för dessa banker är att dom har allvarliga problem med sin kryptering. Du kan därför inte kan lita på att trafiken till deras sajter är ordentligt krypterad.</p>
<p><strong>Inga banker ligger på den här positionen längre. Bra jobbat av alla fem!</strong></p>
<h2 id="slutligen">Slutligen<a href="#slutligen">#</a></h2>
<p>Det finns väldigt många andra kriterier att sätta betyg på, men jag nöjer mig med detta denna gång. Kanske finns det någon annan som vill fortsätta jämförelsen på sin egen blogg?</p>
<p>Vill du diskutera resultaten vidare finns jag på Twitter: @<a href="http://twitter.com/EmilStenstrom">EmilStenstrom</a></p>
8 insights from using the Narrative clip2014-02-22T16:42:03+01:002014-02-22T16:42:03+01:00http://friendlybit.com/lifelogging/8-insights-from-using-the-narrative-clip/Emil StenströmFor about three weeks, I have been a beta tester and then a regular user of Narrative; a wearable camera that is always on, and that takes two pictures a...
<p>For about three weeks, I have been a beta tester and then a regular user of <a href="http://getnarrative.com/">Narrative</a>; a wearable camera that is always on, and that takes two pictures a minute. I thought I'd take some time and share my insights from that experience, and the reason why decided to stop using it.</p>
<p>2014 will be a year of wearable tech and Narrative is clearly a front-runner. It's always on, and nicely captures things around you with iPhone photo quality. At the end of the day you connect it to your computer, which uploads the images to private, encrypted, image storage, that you can access through the Narrative app on your phone. A clever clustering algorithm, based on both GPS data and image similarity, clusters the images to make them easier to browse. It works great, and lives up to the promise of capturing your day as it is.</p>
<img class="aligncenter size-full wp-image-922" src="/files/post-media/narrative-medium.png" alt="narrative-medium" width="539" height="310">
<p>So, insights, what did I learn from this experiment?</p>
<p><strong>Asking for permission</strong>. Narrative takes asking for permission to its limits, since it's always taking pictures. Because of that, I think it follows the same rules as taking a photo with your phone (people tend to think of them as two different things, I don't). Just like you ask permission before taking photos with your phone, you need permission before wearing the Narrative clip on around someone. This was my stance from the very beginning. Not everyone agrees with this, more on that below.</p>
<p><strong>Taking pictures vs. Sharing pictures</strong>. Giving someone permission to take pictures, does not mean you automatically get permission to share them. Narrative takes pictures all the time, but they are are not meant to be shared. They are put in the personal diary that is the Narrative app, and are only viewable by one person. Getting permission to wear it while meeting your friends, does not mean you can share the pictures with other people, without getting their permission again. While this might be obvious for the Narrative camera, I think it applies to mobile photos too. "Is it OK if I take a picture of you?" is not the same as "Is it OK if I share a picture of you with my friends?". If you miss this distinction, you will offend people.</p>
<p><strong>Everyday life</strong>. If you are an active Facebook or Instagram user and look at your profile, you will see a very "directed" and prettified version of your life. This "fixed version" might match your experience well (doing new things means more vivid memories), but it does NOT match how your life looks when viewed through Narrative's stream of photos. I do programming, and ~6-8 hours of every workday I look at a computer screen. The photos from Narrative makes this painstakingly clear. This is a very different image from the one I get from looking at Facebook or Instagram, where the only picture shared might be the great theatre performance I watched later that night. This is of course obvious when you think about it, but my guess is that most people don't think about it. I definitely did during these weeks. Facebook and Instagram fundamentally change how we remember things, by reminding us of all the cool stuff we do, and forgetting everyday life.</p>
<p><strong>Everyday life of your friends</strong>. The difference between your social profiles and your Narrative photo stream of course applies to other people as well. When you look at your friends' social profiles, know that what you see very different from their everyday life. We live in a time where we focus too <a href="http://waitbutwhy.com/2013/09/why-generation-y-yuppies-are-unhappy.html">much of our attention on other peoples experiences</a>.</p>
<p><strong>Asking for permission is uncomfortable</strong>. No matter how strict you are in your policy about sharing the pictures you take, there will be a couple of uncomfortable minutes of explaining how the camera works to new people. People assume that the photos are shared automatically. They assume that you just asked for permission on a whim, and could just as easily forgotten about it. This of course goes away with some explaining, but it's a very bad place to be with people you don't know that well. As someone that takes pride in trying to meet new people often, this is a severe blow to the experience using Narrative. A blow hard enough that I decided the camera wasn't for me.</p>
<p><strong>Not everyone will ask for permission</strong>. Not everyone using Narrative will ask for permission first. I've met people that decided not to, arguing that if you have showed something to them, it makes sense that you allow them to see it again. I understand this line of reasoning, but I think the problem really is with allowing a digital file is where the problem lies. <a href="http://www.snapchat.com/">Snapchat</a> raised the bar on what kind of pictures you could send to your friends, but deleting them after a set amount of seconds. The Narrative images are permanent files. Even though they are not shared, there's the potential of them being shared, and that's bad enough.</p>
<p>So I don't agree with this line of reasoning, but there will be no way of stopping these people from taking pictures of you anyway, and potentially sharing them with their friends. Personally, I think I'm fine with the "taking pictures" part, especially if it's in a public setting: a subway station, a mingle event, or a large party. If it's a private setting with fewer people, I would like to be asked. If I trust the person, I would most often be OK with having pictures of me in a private setting too, but again, I would like to be asked when that person wanted to share the picture with other people. These are my own thoughts, and I don't assume yours to be the same.</p>
<p>My thinking around this means I won't have a problem with other people not asking for permission, since this will happen mostly in public settings. In more private settings I will have to talk to them, and understand their policy around sharing the pictures with friends.</p>
<p>Again: No matter what set of rules you think people should follow when taking pictures of you, your policy when <em>taking pictures yourself</em> should be <em>at least</em> as strict. If you don't expect people to take photos of you using a Narrative camera, don't take photos of them using your mobile camera without asking first. And ask again before sharing.</p>
<p><strong>Different forms of sharing</strong>. Sharing does not necessarily mean sharing on Facebook or Instagram. It could just as easily mean showing someone your phone when having the Narrative app open. It could mean having the file on your computer and then flipping past it when looking for other stuff to show your friends. It could mean inadvertent sharing when you get hacked, get your computer or phone held as evidence in a police investigation, or your government spying on you (NSA).</p>
<p>Sharing is tricky, and I've heard people reasoning around it in terms of what group you share to. Some people are OK with government spying since only a few analysts will see their stuff. Other people are OK with you sharing a picture on Facebook if they know you have reasonable privacy settings. Your mileage may vary, but I wouldn't be surprised if the answer to "Can I share this?" will be highly dependent on the group of people that you share to. Now, the people you share to, and the people that are likely to see something you share, are a much smaller group (EdgeRank), and this makes it even more complicated to value how much privacy you are giving away by allowing someone to share something.</p>
<p><strong>Sound</strong> <strong>and video</strong>. Another common question I've gotten was if I'm recording sound and video. The answer is no, and I think this is a good thing. I hadn't thought of this before, but sound is much more intimate than pictures are. Sound is closer to your thoughts, and sharing someone saying something stupid is much more revealing than a picture of them looking stupid. Pictures rarely portray thoughts. Sound raises the bar considerably, and would make all the interaction around the clip even more difficult. I'm not sure people asking for sound and video support to be added to Narrative have considered the social aspects properly.</p>
<p>***</p>
<p>And that's it, my thoughts around the Narrative clip and what I've learnt from it. I hope you have learnt something too. Don't take this as a reason not to try the camera, it's very opinionated, and you might handle the social aspects better than I did.</p>
<p>Feel free to leave a comment if something needs clarification or if I can answer any questions about my experience.</p>
My text editor: Sublime Text2012-07-07T23:53:03+02:002012-07-07T23:53:03+02:00http://friendlybit.com/tools/my-text-editor-sublime-text/Emil StenströmWhat text editor you use when coding is a very serious subject. I'll hardly be able to talk about what I prefer, without some people (other than you, of...
<p>What text editor you use when coding is a very serious subject. I'll hardly be able to talk about what I prefer, without some people (other than you, of course ;) taking it as me trying to steal their editor from them. I'm not going to. I'm just going to tell you what I think, and you can just decide of you agree or not. My hope is that it helps you be more certain about your own choice of editor.</p>
<p>What I look for in a text editor:</p>
<ol>
<li><strong>Support both Mac and PC</strong>. I use a Mac for work, and a PC at home, and I want to be able to use the editor skills I've learned at work for my hobby projects, and vice versa.</li>
<li><strong>Less than 3 seconds starting time</strong>. Big projects means lots of little files to open. So while programming I will open files and close files all the time. Each delay waiting for the editor to open, or a file to load, means hundreds of seconds over time.</li>
<li><strong>Syntax highlighting for web languages</strong>. I work with web stuff, both front end and back end, and I need colors to be able to scan files quickly. I don't really care about the exact ones, light or dark, I just want it to look decent. What "web languages"? HTML, CSS, Javascript, JSON, Python (Django), Ruby (Rails), PHP, SQL.</li>
<li><strong>Handle big files</strong> <strong>(< 1 Gb)</strong>. From time to time I work with big files. Can be database dumps or large text files. I'm not expecting < 3 sec to open them, but at least < 15 sec, and then be able to work with the file without the editor lagging.</li>
<li><strong>Some kind of file browsing/project support</strong>. There's never just one file and there's needs to be a way to overview all the files in a certain directory structure, and pick from them. I'd like there both to be file searching support and a way to click to a file through the directory structure.</li>
<li><strong>Code auto-completion for web languages</strong>. Do I use font-variant, font-style, or font-decoration to set italic? I want my editor to show me a list of options, and let me pick. This is harder to do well for the dynamic server-side languages, but I still want it.</li>
<li><strong>Look good</strong>. I don't want something that looks like the terminal, and want something beautiful. For me this means gradients, nice rounded tabs to click on, a nice font, a color scheme that matches.</li>
</ol>
<p>With that list of priorities in mind, let's look at a couple of popular editors:</p>
<ul>
<li>Editors that are not available both for Mac and PC: <strong>Textmate</strong>, <strong>Coda,</strong> <strong>Notepad++</strong>, and <strong>Visual Studio</strong>.</li>
<li>Editors that are slow: <strong>XCode, Eclipse</strong>, <strong>NetBeans</strong>, <strong>Dreamweaver</strong>, and most other editors built with Java.</li>
<li>Editors that don't handle syntax highlighting and code completion: <strong>Notepad</strong>, <strong>Wordpad</strong>.</li>
<li>Editors that don't handle big files well: <strong>Komodo Edit</strong> (what I used til recently).</li>
<li>Editors that look like shit: <strong>Emacs</strong>, <strong>Vim</strong>.</li>
</ul>
<p>And then there's <a href="http://www.sublimetext.com/"><strong>Sublime Text</strong></a>. Which does all of the above, perfectly. You should try it.</p>
[The Listserve] I’m sorry to break this to you2012-04-19T13:02:33+02:002012-04-19T13:02:33+02:00http://friendlybit.com/other/the-listserve-im-sorry-to-break-this-to-you/Emil StenströmI just got the fantastic chance to send an e-mail to ~10.000 people. What would you write if you got that chance? This is what I wrote: "I'm sorry to break...
<p>I just got the fantastic chance to send an e-mail to ~10.000 people. What would you write if <a href="http://thelistserve.com/">you got that chance</a>? This is what I wrote:</p>
<blockquote>
<p>"I'm sorry to break this to you, in an e-mail from a random stranger like this, but it needs to be said: Most of your life won't be fantastic. I'm not joking. The adventures you'll tell your children about will be a minuscule part of it. So if you want to avoid the feeling of utter disappointment as you grow older, you need to accept that fact. Sorry.</p>
<p>This leads us to the insight: You should focus more on the non-fantastic parts. The parts where you eat breakfast, walk to the bus, have a boring day at work, eat your ordinary lunch, shop groceries, and brush your teeth. After all, this is the major part of your life, and neglecting it is a wasted opportunity.</p>
<p>Here's the thing: Most of the boring stuff in your life is so dull, that even the tiniest thing can make it seem fun. The tiniest thing. This means the you could make it better with extremely simple means.</p>
<p>What exactly am I talking about here? Little things. Like these:</p>
<ul>
<li>Challenges: When brushing your teeth tonight, use your left hand.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>Mind games: When you enter work (or school!), imagine the sound "Kabaaaam!" as you enter, as if your presence changed the whole room.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>Action: Jump down from the side-walk, instead of just stepping down.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>Changes: Buy some fancy tomato sauce tonight, instead of your usual brand.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>More action: Count the number of pink things on your way to work, as if your life depended on it.</li>
</ul>
<p>See? Easy stuff. I really try to live by this "Everyday Action" idea, and I think it works for making the boring parts of life more fun. Because that's the thing: just because the fantastic moments are few, there's no reason to just sit there, waiting for the next big thing to swipe you off your feet. Have some fun meanwhile, it's easy…"</p>
</blockquote>
<p><a href="http://thelistserve.com/">Sign up for Thelistserve</a>. I'm guessing there's more inspiration to come…</p>
What movies on Piratebay will you like the most?2012-01-08T22:07:29+01:002012-01-08T22:07:29+01:00http://friendlybit.com/python/what-movies-on-piratebay-will-you-like-the-most/Emil StenströmChristmas, and the weeks thereafter, are times for coding. And I've been playing around with piratebay and filmtipset (a Swedish movie recommendation) a...
<p>Christmas, and the weeks thereafter, are times for coding. And I've been playing around with <a href="http://thepiratebay.org">piratebay</a> and <a href="http://filmtipset.se">filmtipset</a> (a Swedish movie recommendation) a little bit. I just pushed it to the <a href="https://github.com/EmilStenstrom/filmtipset-piratebay">filmtipset-piratebay project on GitHub</a>, if you want to take a look.</p>
<h2 id="css-for-screen-scraping">CSS for screen scraping<a href="#css-for-screen-scraping">#</a></h2>
<p>The script is using <strong>CSS for screen scraping</strong>; something that works extremely well:</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">lxml</span><span class="w"> </span><span class="kn">import</span> <span class="n">html</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">requests</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"http://thepiratebay.org/browse/207/0/7"</span><span class="p">)</span>
<span class="n">document</span> <span class="o">=</span> <span class="n">html</span><span class="o">.</span><span class="n">document_fromstring</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
<span class="n">links</span> <span class="o">=</span> <span class="n">document</span><span class="o">.</span><span class="n">cssselect</span><span class="p">(</span><span class="s2">".detLink"</span><span class="p">)</span>
<span class="nb">print</span> <span class="p">[</span><span class="n">link</span><span class="o">.</span><span class="n">text_content</span><span class="p">()</span> <span class="k">for</span> <span class="n">link</span> <span class="ow">in</span> <span class="n">links</span><span class="p">]</span>
</pre></div>
<p>Note: You need <a href="http://lxml.de/">lxml</a> and <a href="http://docs.python-requests.org">requests</a> to run the above example.</p>
<p>Saving the above snippet to a py-file and running it will give you a list of all torrents on the given url. Play around with the CSS selector to get some other data from the page.</p>
<h2 id="extracting-movie-titles-from-torrent-names">Extracting movie titles from torrent names<a href="#extracting-movie-titles-from-torrent-names">#</a></h2>
<p>It's surprisingly easy to convert torrent names to movie titles. Just follow this simple algorithm:</p>
<ol>
<li>Split the torrent name into words by treating all non-alphanumeric characters as space.</li>
<li>Loop over the remaining words, and look for a predefined set of "torrent endings".</li>
<li>When you find an ending, cut the name from there</li>
<li>(Optional) Remove the year if there is one at the end of the remaining string</li>
<li>(Optional) Remove all movies which really are bundles of movies, and not single movies. This is easily done by looking for a set of common strongs such as "trilogy" and "series"</li>
</ol>
<p>Result: "Real.Steel.2011.720p.BluRay.x264-REFiNED" -> "Real Steel"</p>
<p>You can find my movie title finder implementation in parse.py on GitHub.</p>
<h2 id="cache-all-http-request">Cache all HTTP Request<a href="#cache-all-http-request">#</a></h2>
<p>To both save time, and be nice to the services we're querying, the script caches all HTTP requests for a number of days. I do this by simply saving the returned HTML/JSON to a file, and checking the file system for that file before making a new request. Saving the HTML/JSON, and not the processed result, makes it possible to experiment with the parsing, without having to wait for new requests from the server.</p>
<p>My caching implementation is of course also on GitHub.</p>
<p>***</p>
<p>All and all, this has been a fun little project, and I've learned a lot. But I'm sure we can make this even better. Feel free to send pull requests!</p>
Partial XMLHttpRequest responses?2012-01-08T15:28:49+01:002012-01-08T15:28:49+01:00http://friendlybit.com/js/partial-xmlhttprequest-responses/Emil StenströmWe all know how to make an AJAX request, and fetch some data. But as soon as you need to fetch data incrementally, have the server push data to you, you...
<p>We all know how to make an AJAX request, and fetch some data. But as soon as you need to fetch data incrementally, have the server push data to you, you have to resort to all sorts of complicated stuff. Websockets; with all their different versions and shady support, different kinds of polling, hidden iframes, ActiveX for IE?</p>
<p>The simplest way, that almost workds is partial XMLHttpRequest responses. I first read about them as <a href="http://www.kylescholz.com/blog/2010/01/progressive_xmlhttprequest_1.html">progressive xmlhttprequests on Kyle Schulz blog</a>, but really think that method should get more recognition.</p>
<p>Note: I've only tested this with Webkit, against Twitter's Streaming API, with a XMLHttpRequest that allows cross-domain requests. I think it works with Firefox too, but it will definitely not work in IE. Sorry.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">xhr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">XMLHttpRequest</span><span class="p">();</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"<streaming-url-on-you-own-domain-or-CORS>"</span><span class="p">;</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="s2">"GET"</span><span class="p">,</span><span class="w"> </span><span class="nx">url</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">);</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span><span class="p">();</span>
<span class="c1">// Define a method to parse the partial response chunk by chunk</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">last_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="kd">function</span><span class="w"> </span><span class="nx">parse</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">curr_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">last_index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">curr_index</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="p">;</span><span class="w"> </span><span class="c1">// No new data</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">last_index</span><span class="p">,</span><span class="w"> </span><span class="nx">curr_index</span><span class="p">);</span>
<span class="w"> </span><span class="nx">last_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">curr_index</span><span class="p">;</span>
<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Check for new content every 5 seconds</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">interval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">setInterval</span><span class="p">(</span><span class="nx">parse</span><span class="p">,</span><span class="w"> </span><span class="mf">5000</span><span class="p">);</span>
<span class="c1">// Abort after 25 seconds</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
<span class="w"> </span><span class="nx">parse</span><span class="p">();</span>
<span class="w"> </span><span class="nx">xhr</span><span class="p">.</span><span class="nx">abort</span><span class="p">();</span>
<span class="p">},</span><span class="w"> </span><span class="mf">25000</span><span class="p">);</span>
</pre></div>
<p>The biggest problem with this method is that the responseText property keeps filling up with data. The longer you receive data, the bigger the data in memory will be. The only way I can see this fixed (today) is to simply kill the connection after a certain amount of data has been received, and open it up again.</p>
<p><strong>I would love to see a better way to do this</strong>, from native javascript, without all the numerous hacks that are out there. If you know of a way that fills these requirements, please let me know:</p>
<ol>
<li>Easy to implement on the <strong>client side</strong>. Ideally I would like to use XMLHttpRequest, and just get a callback each time the client sends data, with the NEW data specified as a callback parameter.</li>
<li>Easy to implement on the <strong>server-side</strong>. I can set some headers if you make me, but ideally I would like to use this against existing Streaming APIs (like Twitter's), without adding custom stuff.</li>
<li>As cross-browser, cross-platform as possible.</li>
</ol>
<p>Is there a way to get this working? It's so annoying to see something that's a curl one-liner, be 100s of lines of code with web technologies…</p>
<div class="highlight" data-language="BASH"><pre><span></span>curl<span class="w"> </span>https://stream.twitter.com/1/statuses/filter.json?track<span class="o">=</span><your-keyword><span class="w"> </span>-u<span class="w"> </span><your-twitter-nick>
</pre></div>
<p><strong>Is the web really that far behind?</strong></p>
Suggestions for TweetDeck2011-07-22T12:35:04+02:002011-07-22T12:35:04+02:00http://friendlybit.com/ui/suggestions-for-tweetdeck/Emil StenströmTo be an effective twitter user you really need a permanent window on your desktop, that shows you what's happening right now. I've been using TweetDeck for...
<p>To be an effective twitter user you really need a permanent window on your desktop, that shows you what's happening right now. I've been using <a class="zem_slink" title="TweetDeck" href="http://www.tweetdeck.com" rel="homepage">TweetDeck</a> for a long time now, with short detours into <a class="zem_slink" title="seesmic" href="http://seesmic.com" rel="homepage">Seesmic</a> and various smaller clients. TweetDeck is the best client I've found for my needs, but its interface has lots of little bugs and inconsistencies; small things that together add up to a bad user experience.</p>
<p>I hope someone from TweetDeck reads this, and can start working on these (simple) issues. I really think they would improve the general user experience a lot.</p>
<ol>
<li><strong>Compose pane should close after a tweet as been sent</strong>. I've looked over the shoulder of lots of people using TweetDeck, and the most common pattern is to click the reply button on someone's avatar to write a new message. If writing multiple messages directly after eachother was more common than writing them one by one, then it should stay open, but that's not the case.</li>
<li><strong>Tweets should be as compact height-wise as they can be</strong>. All tweets in TweetDeck are displayed as if they where full 140 chars. This means that valuable screen space is lost, something TweetDeck pushes one of its advantages over the official Twitter client or the web. "More Tweets per screen!". What's worse, having tweets aligned horizontally over several columns makes it look like there's some connection between then. Why do they align my third timeline tweet with my third mention? No idea.</li>
<li><strong>All retweets should be shown, not only the last one</strong>. Retweets are a very important part of Twitter. By seeing who retweets you, you learn who your active followers are, and maybe even find people that are interesting for you to follow. But TweetDeck does not follow the lead of the official client that shows "Retweeted by [user] and 3 others", instead they show just the last one.</li>
<li><strong>The buttons at the bottom of each column should be hidden</strong>. The bottom buttons of each column are for things that people rarely use, but they still are allowed to permanently take of screen estate. Instead they should be hidden behind one button, and put at the top of the window with the column title. This would leave even more space for tweets to be shown.</li>
<li><strong>The "Quick jump to column" buttons at the bottom of the window should be removed</strong>. Having clickable icons that set the scroll offset is a very strange interface concept. I understand the need to jump between columns when you have 10-15 columns, but most people don't have that. Letting an interface element that is used seldom by most people take up that much space is just a waste. It users with that many columns is an important part of the target audience, use tabbed workspaces instead. Each workspace could show up as a tab at the top of the window, and each workspace could have its own set of columns. Until that's done, remove the clunky icons at the bottom and free more space for tweets.</li>
</ol>
<p>Here's a quick sketch of how TweetDeck looks <em><strong>before</strong></em> any changes:</p>
<p><a href="/files/post-media/tweetdeck_original.png" data-no-instant><img class="alignnone size-full wp-image-824" title="tweetdeck_original" src="/files/post-media/tweetdeck_original.png" alt="" width="730" height="612"></a></p>
<p>… and here's the same view <strong>*after*</strong> the five interface improvements have been implemented:</p>
<p><a href="/files/post-media/tweetdeck_redesign1.png" data-no-instant><img class="alignnone size-full wp-image-826" title="tweetdeck_redesign" src="/files/post-media/tweetdeck_redesign1.png" alt="" width="730" height="612"></a></p>
<p>These are changes I really would like to see in TweetDeck, what do you think?</p>
Fixing Microsoft’s bad reputation2011-06-19T14:07:32+02:002011-06-19T14:07:32+02:00http://friendlybit.com/strategy/fixing-microsofts-bad-reputation/Emil StenströmMicrosoft has continuously failed at getting people in the tech crowd to like them. This is a growing problem for them, and something they need to start...
<figure class="wp-caption alignright"><a href="http://www.flickr.com/photos/88442983@N00/2228633614"><img title="Blue Screen of Death" src="/files/post-media/2228633614_e26ea98fbe_m.jpg" alt="Blue Screen of Death" width="240" height="187" /></a>
</figure>
<p>Microsoft has continuously failed at getting people in the tech crowd to like them. This is a growing problem for them, and something they need to start taking seriously. To understand how to turn this around, let's start a decade ago, with Slashdot.</p>
<p><strong><a href="http://slashdot.org/">Slashdot</a></strong> has always been one of the pillars of Microsoft-negative news. They have a whole <a href="http://slashdot.org/index2.pl?fhfilter=microsoft">category on Microsoft</a> (And the others have lots of articles too: <a href="http://digg.com/search?q=microsoft">"Microsoft" articles on Digg</a>, <a href="http://www.reddit.com/search?q=microsoft">"Microsoft" articles on Reddit</a>, "Microsoft" articles on Hacker News). With a few exceptions, articles (and comments) are about Microsoft using their monopoly to crush smaller businesses, how their technology is inferior to what the open source world creates, on them creating data lock-in where users are unable to switch away from them, and so on. Slashdot, Digg, Reddit, Hacker News together have millions of daily users, who place as much faith in them as others do in their morning newspaper.</p>
<p>But these sites are only read by disgruntled teens right? No. Hacker news users are ~26, <a href="http://www.reddit.com/r/reddit.com/comments/7oaxh/experiment_how_old_is_the_average_redditor_vote/?sort=top">Reddit users are ~24</a>, <a href="http://www.ignitesocialmedia.com/social-media-stats/2011-social-network-analysis-report/#Digg">Digg users are 35-44</a>… When asked: "What computer do you want?" These users answer: "<strong>A Mac (or Linux) laptop</strong>". When asked: "What software? They answer: "<strong>Google Docs (or LibreOffice/OpenOffice)</strong>". All those individual choices are starting to pile up, and have far-reaching consequences for Microsoft: Windows and Office licenses are the <a href="http://www.businessinsider.com/chart-of-the-day-microsoft-operating-income-by-division-2010-2">major part of Microsoft's income</a>. Choosing a Mac or Linux laptop means no Microsoft Windows, choosing Google Docs or LibreOffice/OpenOffice means no Microsoft Office.</p>
<p><strong>Tech users are a major force</strong> inside real companies, and not something Microsoft can just ignore. What about beginners and business users? They are both heavily influenced by by tech users. Beginners because they ask others for advise before buying their computers and software. Business users are instead controlled by their IT departments, which in turn try to find the most knowledgeable tech people to work for them. The small hold Microsoft still have on some IT departments is slowly shifted away from them when employees get empowered to choose their own equipment, moving them from business users to beginners in their purchase patterns. The tech crowd has more influence than you'd think.</p>
<p>Question is: <strong>where do you start</strong> fixing all this distrust? There's only one way: you start talking to tech users on their own terms. Here's how I would do it:</p>
<ol>
<li>Hire some good of <strong>community managers</strong>. Their job will not be to market Microsoft, but to be the communication channel that can aggregate community opinions to Microsoft. The more rooted they already are in their respective communities the better; that makes it easier to start get the discussion started at a respectful level. You don't yell "Microsoft sucks!" at someone you respect.</li>
<li>Start by <strong>monitoring news</strong> about Microsoft and send monthly reports to managers inside Microsoft. Couple each news item with an approximate number of users that read them. This will paint an image of how tech users see the Microsoft brand. Pretty soon they will want to change that image.</li>
<li>Use community managers to ask for <strong>opinions on what to do next</strong>. Ask for small things that are likely easy to get done, and make sure to manage expectations right away. Windows 8 won't be open sourced :)</li>
<li>Have a <strong>small engineering team</strong> whose sole purpose is to make the suggestions from the tech crowd happen. They need to be cross-disciplinary, be well connected across the company, and have mandate from high up the organization. Employing this team is a small cost compared to other forms of marketing. Feed back any progress they make back as articles where they fit.</li>
<li>Lastly: Use insights from community managers to create <strong>marketing campaigns directly aimed at the tech crowd</strong>. A good community manager can have a pretty good guess at what work and what will. Many of the things will not only be marketing, but also require engineering, but there already is a team for that.</li>
</ol>
<p>Working through that list will make Microsoft slowly earn their trust back from the tech crowd. It won't happen overnight; you don’t reverse 10 years of silence that fast. But I think this is doable, reasonable, and something that really could work.</p>
<p>Would you be willing to be a community manager for Microsoft? What would you suggestion Microsoft did to please the tech crowd? I'd love to hear your opinions.</p>
Geolocation and Google maps2011-06-18T14:11:11+02:002011-06-18T14:11:11+02:00http://friendlybit.com/js/geolocation-and-google-maps/Emil StenströmImage by heiwa4126 via Flickr Google Maps has has geolocation support for a long time, but I still find people surprised of how it all works. So here's a...
<div class="zemanta-img">
<figure style="width: 240px" class="wp-caption alignright"><a href="http://www.flickr.com/photos/57552634@N00/3791431635"><img title="Google Maps Marker in Tokyo" src="/files/post-media/3791431635_c722c1d51a_m.jpg" alt="Google Maps Marker in Tokyo" width="240" height="120" /></a><figcaption class="wp-caption-text">Image by heiwa4126 via Flickr</figcaption></figure>
</div>
<p>Google Maps has has geolocation support for a long time, but I still find people surprised of how it all works. So here's a short writeup, skip it if you already know all about geolocation.</p>
<p><strong>Lets start</strong> at the <a title="Google Maps" rel="homepage" href="http://maps.google.com/">Google Maps</a> frontpage. Among the zoom controls, above the little old man, there's a button in the form of a small circle. It does not look like much, but what it's doing is incredibly cool. Click it and the map moves to where you are, with an accuracy of ~20 meters. Sci-fi crazy!</p>
<p><strong>How does it work?</strong> In the newer browsers (all but IE6, IE7, or IE8) may ask you for your positioning information from the browser. It usually shows up as a bar at the top of the browser. The browser then gathers two specific forms of positioning information from your computer: your <strong>IP address</strong> and the <strong>signal strength of any wireless network</strong> near you. That information is then sent, if you approve it, to Google, which returns the coordinates you are at the moment.</p>
<p>Google can do this because they've been driving around with their street view cars all over the world, and measured signal strength of WiFi networks (public and private) at each specific location. Now they can use that information, combined with your local signal strength conditions, to triangulate their way to where you are. And it's both accurate and fast.</p>
<p>If your wireless reciever is turned off, or you're at a stationary computer, all calculations are based on the IP number. These kind of lookups are quite arbitrary and inaccurate, I just get to the nearest big city when trying to use it over a non-wireless line. But mobile connections are slowly taking over landlines, so I guess this problem will solve itself automatically.</p>
<p>The best kind of technology throws you forward in time, and make your realize that we're actually making progress. Geolocation has feel to it.</p>
<p>Looking for the techy explaination of geolocation? Have a look at <a href="http://robertnyman.com/2010/03/15/geolocation-in-web-browsers-to-find-location-google-maps-examples/">Robert Nyman's writeup</a>.</p>
Animate from one element to another (jQuery plugin)2011-05-05T22:52:14+02:002011-05-05T22:52:14+02:00http://friendlybit.com/js/animate-from-one-element-to-another-jquery-plugin/Emil StenströmImage via Wikipedia Have you even tried clicking an "Add to cart"-button and not understood what happened? I have. An although I understand the idea of...
<div class="zemanta-img">
<figure style="width: 215px" class="wp-caption alignright"><a href="http://commons.wikipedia.org/wiki/File:Stencil_shopping_cart.jpg"><img title="Stencil of a shopping cart with the head of th..." src="/files/post-media/300px-Stencil_shopping_cart31.jpg" alt="Stencil of a shopping cart with the head of th..." width="215" height="162" /></a><figcaption class="wp-caption-text">Image via Wikipedia</figcaption></figure>
</div>
<p>Have you even tried clicking an "Add to cart"-button and not understood what happened? I have. An although I understand the idea of adding a product to the cart, and then letting the user continue browsing from where he is, I still get stumped when "nothing happens" when I click the button. So what to do?</p>
<p>Simple: Add a <strong>animation from the add button to the cart</strong>. That way you communicate what just happened. "The product moved in there, and by clicking the cart you'll find it again. Now continue buying stuff!".</p>
<p>Somebody must have done this before, so I started looking for a <a class="zem_slink" title="JQuery" rel="homepage" href="http://jquery.com/">jQuery</a> plugin to do this (jQuery was already on the page, so why not?). I found add2cart - A plugin that looks good, but that misses a few features I wanted:</p>
<ul>
<li>The <strong>animation duration</strong> is set in seconds, meaning products further down the page will move faster than those further up. I wanted constant speed.</li>
<li>It didn't allow me to <strong>customize the look</strong> of the animated element.</li>
<li>The code rely on concatenating strings of CSS and generally could use <strong>lots of improvement</strong>.</li>
</ul>
<p>So I did what anyone would do: rewrote the code from scratch, and posted it on GitHub.</p>
<p><strong>Get the code: <a href="https://github.com/EmilStenstrom/jQuery-animate_from_to">Animate From To 1.0</a></strong></p>
<p>It's my first jQuery plugin ever, and my first public GitHub project, so let me know if I've done something wrong. Is this something that could be useful in one of your projects?</p>
Will newspapers die?2011-02-09T00:41:17+01:002011-02-09T00:41:17+01:00http://friendlybit.com/modern-web/will-newspapers-die/Emil StenströmA journalism student in Toronto, Canada, asked me some questions via e-mail about my old article about newspapers and online reading. Instead of just...
<p>A journalism student in Toronto, Canada, asked me some questions via e-mail about my old article about <a href="/modern-web/why-people-skip-newspapers-and-read-news-on-the-web-instead/">newspapers and online reading</a>. Instead of just sending an e-mail out in the void I thought I'd persist my answers here:</p>
<blockquote>
<ol>
<li>Do you think it would be best for newspaper publications to get rid of their print and go strictly online only? Why or why not?</li>
</ol>
</blockquote>
<p>I think they should keep their print papers for a while longer. It's a simple question of profit and catering to what users want. If you have thousands of users that want their paper, and it's economically justifiable, just keep it.</p>
<p>The tricky part is determining how much loss in paper subscribers you should tolerate before shutting down the huge printing presses. I have no good answer to that other than to know your numbers. Paper profit needs to cover paper printing and distribution. Journalism costs can be split between channels. Do the math.</p>
<blockquote>
<ol start="2">
<li>Many people believe newspapers are dying and eventually will no longer exist. What are your thoughts on this?</li>
</ol>
</blockquote>
<p>I think they will persist, just not their paper versions. Many of them are looking at dwindling subscription numbers, year after year, and are trying to figure out what to do. How do you move to the digital worlds while keeping quality, relevance, and profit.</p>
<p>The iPad is one way to get people to pay for news again, and some newspapers are seeing success doing that. Over a longer haul just the iPad won't be enough, you need to be able to deliver your news to wherever your customers want them. Generally, this means being able to get your content on all kinds of devices, both mobile and desktop. The only format that can really do that, and still deliver a somewhat consistent design across devices, is HTML and CSS. Building one native app for each platform is just not worth it.</p>
<p>So it's simple really: newspapers that figure out how to transition to digital (while still getting paid enough to afford quality journalism) will persist, all others will (slowly) die. This means an end to both paper-only newspapers, and those that fail to find the right payment model.</p>
HTML5 is not an option2010-11-03T20:20:42+01:002010-11-03T20:20:42+01:00http://friendlybit.com/html/html5-is-not-an-option/Emil StenströmHTML5 is HOT! Developers all over the world are adapting their sites, browsers are catching up, and new fallback solutions are released every day. But many...
<p>HTML5 is HOT! Developers all over the world are adapting their sites, browsers are catching up, and new fallback solutions are released every day. But many developers misunderstand one thing:</p>
<blockquote>
<p><strong>You can't choose to use HTML5 or not, your site will be parsed as HTML5 no matter what.</strong></p>
</blockquote>
<p><img class="alignnone size-full wp-image-656" style="max-width: 100%;" title="no-choice" src="/files/post-media/no-choice-e1288811809935.jpg" alt="Voting is pointless. I am your leader now. It is useless to resist me." /></p>
<p>The reason is simple, HTML5 is made to be backwards compatible with the current web, so browsers don't need to keep their current parsers. All of them have soon switched to HTML5 parsers. You want to continue using HTML4? Not possible.</p>
<p>Now. You <strong>can</strong> choose whether you want to use the new features or not: New semantic tags, Microdata attributes, new form field types, accessibility features, 10-15 new JavaScript API:s (depending on how you count). Lots of new interesting stuff to learn.</p>
<p>So, go read up on HTML5 if you haven't already, but don't think you can keep using HTML4. Your site is being switched over as we speak.</p>
Lazy Loading Asyncronous Javascript2010-05-08T00:15:06+02:002010-05-08T00:15:06+02:00http://friendlybit.com/js/lazy-loading-asyncronous-javascript/Emil StenströmUpdate: This is no longer the best way to load scripts. Use a script tag with async and defer set instead. Like many of you might know, I'm working on a...
<p><strong>Update:</strong> This is no longer the best way to load scripts. Use a <a href="https://www.igvita.com/2014/05/20/script-injected-async-scripts-considered-harmful/">script tag with async and defer set</a> instead.</p>
<p>Like many of you might know, I'm working on a site called <a href="http://kundo.se">Kundo</a> with a couple of friends. It's kinda like a Swedish version of <a href="http://getsatisfaction.com/">Getsatisfaction</a>, which means we have a javascript snippet that people add to their site to get feedback functionality. Cut-and-paste instead of writing the code yourself. Simple.</p>
<p>The problem is, how do you load an external javascript with minimal impact on your customer's sites? Here are my requirements:</p>
<ol>
<li><strong>Small</strong>. I don't want a big mess for them to include on their sites. 10-15 lines, tops.</li>
<li><strong>Stand-alone</strong>. The environment is unknown, so we can't rely on any external dependencies, like javascript libraries.</li>
<li><strong>Cross-browser</strong>. I have no idea what browsers my customer's customers have, so I can't do anything modern or fancy that isn't backwards compatible. I assume at least IE6 and up though.</li>
<li><strong>Asynchronous download</strong>. The download of my script should not block the download of any script on their sites.</li>
<li><strong>Lazy Loading</strong>. If my site is temporarily slow, I don't want to block the onload event from triggering until after our site responds.</li>
<li><strong>Preserve events</strong>. Any events used should not override any events on the customer's site. Minimal impact, like I said.</li>
<li><strong>Don't pollute namespace</strong>. Global variables should be avoided, since they could conflict with existing javascript.</li>
</ol>
<p>Note: I did not make all of this up myself. Lots of people did, I'm just writing it down for you. Thanks: Jonatan, <a href="http://stevenbenner.com/">Steven</a>, <a href="http://fleecelabs.se/">Peter</a>, and <a href="http://hanssonlarsson.se/">Linus</a>.</p>
<h2 id="script-tag">Script tag<a href="#script-tag">#</a></h2>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"http://yourdomain.com/script.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</pre></div>
<p>While being the stand-alone, cross-browser, and the shortest piece of code possible; it doesn't download asynchronously and doesn't lazy load. <strong>Fail</strong>.</p>
<div style="overflow: auto;">
<img class="alignnone size-full wp-image-619" title="Firebug screenshoot with script tag" src="/files/post-media/script11.png" alt="" width="725" height="70" />
</div>
<p><em><strong>Screenshot from Firebug's net console:</strong> The script (set to load in 2 seconds) blocks the download of the big image (added after the above script tag, and used throughout this article as a test). Onload event (the red line) triggers after 2.46 seconds.</em></p>
<h2 id="async-pattern-a-script-tag-written-with-javascrip">Async pattern (A script tag written with javascript)<a href="#async-pattern-a-script-tag-written-with-javascrip">#</a></h2>
<p><a href="http://stevesouders.com">Steve Souders</a>, the web performance guru, has compiled a decision tree over <a href="http://stevesouders.com/efws/images/0405-load-scripts-decision-tree-04.gif">different ways to achieve non-blocking downloads</a>. Have a look at that graph.</p>
<p>Since we're on a different domain, and only have one script (order doesn't matter), the solution is given: We should create a script tag with inline javascript, and append it to the document. Voila! Non-blocking download!</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="p">(</span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'script'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'text/javascript'</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="k">async</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">src</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'http://yourdomain.com/script.js'</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">'script'</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">);</span>
<span class="p">})();</span>
</pre></div>
<p><strong>Note</strong>: <code>async</code> is a <a href="http://www.whatwg.org/specs/web-apps/current-work/#attr-script-async">HTML5 attribute</a>, doing exactly what we're trying to simulate with our hack, so it's added for good measure. Also, wrapping the code in an anonymous function prevents any variables to leak out to the rest of the document.</p>
<p>This is a pattern that is getting more and more popular nowadays, especially since <a href="http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html">Google Analytics uses it</a>. But there's an important distinction here: The above snipped <strong>blocks onload from triggering</strong> until the referenced script is fully loaded. <strong>Fail</strong>.</p>
<p><strong>Update 2010-09-01</strong>: <a href="#comment-34047">Steve Souders</a> adds that the above is only true for Firefox, Chrome, and Safari, but not IE and Opera. So for a IE-only site, this might be the best method.</p>
<div style="overflow: auto;">
<img class="alignnone size-full wp-image-617" title="Firefox screenshoot with the async pattern" src="/files/post-media/asyncload11.png" alt="" width="726" height="69" />
</div>
<p><em><strong>Screenshot from Firebug's net console:</strong> The script (set to load in 2 seconds) downloads in parallell with the big image. Onload event (the red line) triggers after 2.02 seconds.</em></p>
<h2 id="lazy-load-pattern-async-pattern-triggered-onload">Lazy load pattern (Async pattern triggered onload)<a href="#lazy-load-pattern-async-pattern-triggered-onload">#</a></h2>
<p>So, how to you make sure you don't block onload? Well, you wrap your code inside a function that's called on load. When the onload event triggers, you know you haven't blocked it.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'script'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'text/javascript'</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="k">async</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">src</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'http://yourdomain.com/script.js'</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">'script'</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>This works, but it overrides the onload event of the site that uses the script. This could be OK in some cases, where you have control over the site referencing the script, but I need to cater for that. <strong>Fail</strong>.</p>
<h2 id="unobtrusive-lazy-load-pattern">Unobtrusive lazy load pattern<a href="#unobtrusive-lazy-load-pattern">#</a></h2>
<p>The logical solution to the above problem is to use an incarnation of addEvent. addEvent is simply a common name for an cross browser way to take the current function tied to onload, add it to a queue, add your function to the queue, and tie the queue to the onload event. So which version of addEvent should we use?</p>
<p>There's been competitions for writing a <a href="http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html">short and compact version of addEvent</a>, and the winner of that competition was John Resig, with this little beauty:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">addEvent</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="w"> </span><span class="nx">type</span><span class="p">,</span><span class="w"> </span><span class="nx">fn</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">obj</span><span class="p">[</span><span class="s1">'e'</span><span class="o">+</span><span class="nx">type</span><span class="o">+</span><span class="nx">fn</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">fn</span><span class="p">;</span>
<span class="w"> </span><span class="nx">obj</span><span class="p">[</span><span class="nx">type</span><span class="o">+</span><span class="nx">fn</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(){</span><span class="nx">obj</span><span class="p">[</span><span class="s1">'e'</span><span class="o">+</span><span class="nx">type</span><span class="o">+</span><span class="nx">fn</span><span class="p">](</span><span class="nb">window</span><span class="p">.</span><span class="nx">event</span><span class="p">);}</span>
<span class="w"> </span><span class="nx">obj</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">(</span><span class="s1">'on'</span><span class="o">+</span><span class="nx">type</span><span class="p">,</span><span class="w"> </span><span class="nx">obj</span><span class="p">[</span><span class="nx">type</span><span class="o">+</span><span class="nx">fn</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="nx">obj</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span><span class="w"> </span><span class="nx">fn</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p><strong>Note</strong>: This is unsafe code, since it relies on serializing a function to a string, something that <a href="http://my.opera.com/hallvors/blog/2007/03/28/a-problem-with-john-resigs-addevent">Opera mobile browsers have disabled</a>.</p>
<p>Thing is, we don't need all that generic event stuff, we're only dealing with onload here. So if we first replace the type attribute with hardcoded 'load', replace obj with 'window', and remove the fix for making 'this' work in IE, we've got four lines of code left. Let's combine this with the above lazy load pattern:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="p">(</span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">async_load</span><span class="p">(){</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'script'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'text/javascript'</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="k">async</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">src</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'http://yourdomain.com/script.js'</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">'script'</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">)</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">(</span><span class="s1">'onload'</span><span class="p">,</span><span class="w"> </span><span class="nx">async_load</span><span class="p">);</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span><span class="w"> </span><span class="nx">async_load</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span>
<span class="p">})();</span>
</pre></div>
<p>This is exactly what we're looking for here. <strong>Finally!</strong></p>
<div style="overflow: auto;">
<img class="alignnone size-full wp-image-618" title="Firebug screenshoot with the lazy load pattern" src="/files/post-media/lazyload11.png" alt="" width="726" height="71" />
</div>
<p><em><strong>Screenshot from Firebug's net console:</strong> The script (set to load in 2 seconds) downloads after the onload event has triggered. Onload event (the red line) triggers after 0.41 seconds.</em></p>
<p>And that wraps up this article: Different tactics works for different scenarios, and only understanding them all makes you capable of picking the right one for your problem. As always, I'm waiting for your feedback in the comments. Thanks for reading!</p>
My iPad – a short review2010-04-25T20:33:32+02:002010-04-25T20:33:32+02:00http://friendlybit.com/modern-web/my-ipad-a-short-review/Emil StenströmAbout two weeks ago, I got my hands on an iPad. For those of you who have been living under a rock for the last months, and iPad is something that looks...
<p>About two weeks ago, I got my hands on an iPad. For those of you who have been living under a rock for the last months, and <a href="http://www.apple.com/ipad/">iPad</a> is something that looks like a big iPhone, but behaves much like a small laptop.</p>
<p>Since people who just spent over $500 for a toy, are very subjective in their judging (buying something bad would make you look stupid!), you have to take this review for what it is: Me trying to justify buying an expensive toy. To help my mind balance things a bit, I'm going to talk about two good things, and two bad things about the iPad.</p>
<ul>
<li><a href="#ipad_ui"><strong>Good</strong>: Looks, UI and surfing the web</a></li>
<li><a href="#ipad_developer"><strong>Bad</strong>: A horrible Developer Platform</a></li>
<li><a href="#ipad_games"><strong>Good</strong>: Games that use the touch interface</a></li>
<li><a href="#ipad_itunes"><strong>Bad</strong>: Downloading apps through iTunes</a></li>
<li><strong><a href="#ipad_summary">Summary</a></strong></li>
</ul>
<h2 id="ipad_ui">Good: Looks, UI and surfing the web<a href="#ipad_ui">#</a></h2>
<figure id="attachment_597" style="width: 300px" class="wp-caption alignleft">
[<img class="size-medium wp-image-597 " title="iPad and Banana" src="/files/post-media/ipad_and_banana-300x225.jpg" alt="" width="300" height="225">](/files/post-media/ipad_and_banana.jpg)
<figcaption class="wp-caption-text">An iPad, here shown next to a old banana for comparison. Click for bigger image.</figcaption>
</figure>
<p>The area where the iPad really shines is when it comes to the look and feel. It's simply gorgeous, feels good in your hand, and makes all your friends instantly drool (like you expect them to). The screen is as sharp (or sharper) than a computer monitor, and its brightness could light up a dark room.</p>
<p>Working with it is just as pleasant. You click, swipe, pinch and type, like you've done nothing nothing else in your life. As someone who haven't used an iPhone before, I'm impressed. Those that have, say that the iPad is even snappier than the iPhone. Some application are of course better fit for a touch interface than others. Google Maps is one of them, when a large display combined with panning and zooming makes the old arrow and zoom buttons on the traditional Google Maps interface feel like stone-age.</p>
<p>They keyboard surprised me by being even better than I expected. In landscape mode it's almost as large as a laptop keyboard, and in some cases even faster than a traditional keyboard since you don't have to push, just touch the buttons. The biggest keyboard problem though is of course that you usually only have one hand available. When you have two hands, it's great.</p>
<p>Another area where the iPad really works is as <strong>a window to the web</strong>. Safari comes pre-installed (Microsoft monopoly anyone?) but works like a charm. Pages load quickly, and swiping to scroll and pinch to zoom works just like it should.</p>
<p>Web standards are well supported, like you expect from Safari. But some new problems emerge when looking at HTML5 demos though:</p>
<ul>
<li>The Safari inside the iPad isn't as performant as a desktop browser. So there's lots of lagging when trying to rotate things in advanced ways.</li>
<li>Even though Apple has decided to ban Flash and pick a fight with Adobe, many new apps are built to take advantage of the mouse moving around. On the iPad, there's no mouse pointer, so you have to simulate one by touching the screen and moving the finger around.</li>
<li>Keyboard navigation is strange, because most of the time, you don't have a keyboard. The keyboard only shows up only when you focus a text field, at other times, you're lost.</li>
</ul>
<p>These things sound like annoyances, and they are, but they are also quite minor. For all the surfing you usually do, the iPad works just like it should.</p>
<h2 id="ipad_developer">Bad: A horrible Developer Platform<a href="#ipad_developer">#</a></h2>
<p>As you've probably heard during the last few weeks, Apple have no clue whatsoever about how to cultivate a vibrant developer community. Let's look at the facts:</p>
<ul>
<li>To distribute your app you need to join the iPhone Developer Program, that costs you $99-$299 per year.</li>
<li>To download the SDK you need to fill out a huge multi-step form (where almost all fields are required), and where you're asked to give away lots of personal information.</li>
<li>When you "publish" your app it has to go through a manual approval process, which could take months if you are unlucky.</li>
<li>You need to approve to a ridiculous legal statement preventing you from using some programming languages, and making calls to some APIs.</li>
</ul>
<p>To quote:</p>
<blockquote>
<p>"3.3.1 — Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited)."</p>
</blockquote>
<p>Needless to say, <strong>I'm never going to be develop anything for the Apple Platform</strong>. Apple and its developers is much like one big company (with strict rules). The only difference is that instead of a salary the developers get to pay to work for them. Good for Apple, horrible for developers.</p>
<h2 id="ipad_games">Good: Games that use the touch interface<a href="#ipad_games">#</a></h2>
<p>There are lots of good games that have started to take advantage of the big touch surface to make fun interaction styles possible.</p>
<ul>
<li><a href="http://itunes.apple.com/us/app/tap-tap-radiation/id364160328?mt=8">Tap Tap Radiation</a> builds on you tapping the screen in pace with the music playing. The place to hit move around, just like the markers that indicate where to tap.</li>
<li><a href="http://itunes.apple.com/us/app/id363998989?mt=8">Asphalt 5</a> is a beautiful racing game where you use the iPad as a steering wheel and tilt it back and fourth to steel. Since the accelerometer is so sensitive it works remarkably well.</li>
<li><a href="http://itunes.apple.com/se/app/n-o-v-a-near-orbit-vanguard/id343596730?mt=8">N.O.V.A. - Near Orbit Vanguard Alliance</a> is a first person shooter that uses gestures to control who you shoot and how. Advanced gestures makes it possible to throw grenades that fly around corners, and targeting multiple enemies at once.</li>
</ul>
<p>Simply put, there are lots of fun games for the iPad, and the reason is experimentation with the touch interface. Combine this with several days of battery power, and you have many hours of fun ahead of you.</p>
<h2 id="ipad_itunes">Bad: Downloading apps through iTunes<a href="#ipad_itunes">#</a></h2>
<figure id="attachment_601" style="width: 152px" class="wp-caption alignleft">
[<img class="size-medium wp-image-601" title="iPad closeup" src="/files/post-media/ipad_closeup-225x300.jpg" alt="" width="152" height="203">](/files/post-media/ipad_closeup.jpg)
<figcaption class="wp-caption-text">A closer look at the iPad, still with the banana present. Click for bigger image.</figcaption>
</figure>
<p>Sadly, the only way to get apps legally into the iPad is through iTunes. Since my iPad was bought in the US, the App Store icon leads to a "Your request could not be completed" with no further info. So it seems that the App Store is only launched in the US. Silly me, that thought the web was an international thing.</p>
<p>Anyway, it is possible to get apps into the iPad without getting a fake american App Store account. You just use iTunes to download the apps to a desktop computer, and then sync your app to the iPad. It's easy.</p>
<p>Well, strike that, using the iTunes store is not easy. Not being a previous iPhone using I had thought that downloading apps from iTunes was like shopping on Amazon. <strong>IT'S NOT EVEN CLOSE</strong>. This is how Apple built iTunes:</p>
<ol>
<li>Take one fully functional e-commerce web site.</li>
<li>Make it slow so that people like me that surf on a 100 Mbit/s fibre connection have to wait several seconds after each click.</li>
<li>Make sure you can only access the store through a special downloadable app, that requires you sign several legal agreements, and leave away personal information, before you even bought anything.</li>
<li>Remove the possibility to sort through listings, remove any information what the list is currently sorted by, and hide options to only show apps for the device they know you just connected (the iPad).</li>
<li>Tada! You've built iTunes!</li>
</ol>
<p>Needless to say, each visit to the iTunes App Store is a bad experience, and no something you want to do often.</p>
<h2 id="ipad_summary">Summary<a href="#ipad_summary">#</a></h2>
<p>Situations where I see myself using my iPad:</p>
<ul>
<li>In bed, watching public television through Svtplay. They have a great app, that is mainly adapted for iPhone, but scales up when used on a bigger screen.</li>
<li>Casually surfing the web from the couch. This includes checking my e-mail (which is IMAP over SSL, which works fine), checking my feeds through Google Reader, checking Facebook through the iPhone app (which can be pixel-doubled to fit the screen nicely), and twitter through twitterific.</li>
<li>Surfing all kinds of maps, and wikipedia in some social context. If I ever get into an argument about where a country is exactly, I'm pull up my iPad instantly and check it.</li>
</ul>
<p>And that concludes this iPad review.</p>
<figure id="attachment_607" style="width: 300px" class="wp-caption alignnone">
[<img class="size-medium wp-image-607" title="iPad turned off" src="/files/post-media/ipad_off_and_banana-300x225.jpg" alt="" width="300" height="225">](/files/post-media/ipad_off_and_banana.jpg)
<figcaption class="wp-caption-text">iPad rests here, next to banana.</figcaption>
</figure>
<p>As usual I'm looking forward to <strong>your thoughts in the comments</strong>. Thanks for reading!</p>
Rendering a web page – step by step2010-01-11T01:04:33+01:002010-01-11T01:04:33+01:00http://friendlybit.com/css/rendering-a-web-page-step-by-step/Emil StenströmHave you ever thought about what happens when you surf the web? It's not as simple as it seems: You type an URL into address bar in your preferred browser....
<p>Have you ever thought about what happens when you surf the web? It's not as simple as it seems:</p>
<ol>
<li>You <strong>type an URL</strong> into address bar in your preferred browser.</li>
<li>The browser <strong>parses the URL</strong> to find the protocol, host, port, and path.</li>
<li>It <strong>forms a HTTP request</strong> (that was most likely the protocol)</li>
<li>To reach the host, it first needs to <strong>translate</strong> the human readable host <strong>into an IP number</strong>, and it does this by doing a DNS lookup on the host</li>
<li>Then a <strong>socket needs to be opened</strong> from the user's computer to that IP number, on the port specified (most often port 80)</li>
<li>When a connection is open, the <strong>HTTP request is sent</strong> to the host</li>
<li>The host <strong>forwards the request</strong> to the server software (most often Apache) configured to listen on the specified port</li>
<li>The <strong>server inspects the request</strong> (most often only the path), and <strong>launches the server plugin needed</strong> to handle the request (corresponding to the server language you use, PHP, Java, .NET, Python?)</li>
<li>The plugin gets access to the full request, and starts to prepare a HTTP response.</li>
<li>To construct the response a <strong>database</strong> is (most likely) <strong>accessed</strong>. A database search is made, based on parameters in the path (or data) of the request</li>
<li>Data from the database, together with other information the plugin decides to add, is <strong>combined into a long string</strong> of text (probably HTML).</li>
<li>The plugin <strong>combines</strong> that data with some meta data (in the form of HTTP headers), and <strong>sends the HTTP response</strong> back to the browser.</li>
<li>The browser receives the response, and <strong>parses the HTML</strong> (which with 95% probability is broken) in the response</li>
<li>A <strong>DOM tree is built</strong> out of the broken HTML</li>
<li><strong>New requests are made</strong> to the server for each new resource that is found in the HTML source (typically images, style sheets, and JavaScript files). Go back to step 3 and repeat for each resource.</li>
<li><strong>Stylesheets are parsed</strong>, and the rendering information in each gets attached to the matching node in the DOM tree</li>
<li><strong>Javascript is parsed and executed</strong>, and DOM nodes are moved and style information is updated accordingly</li>
<li>The browser <strong>renders the page</strong> on the screen according to the DOM tree and the style information for each node</li>
<li><strong>You</strong> <strong>see</strong> the page on the screen</li>
<li>You get annoyed the whole process was too slow.</li>
</ol>
<p>I, too, get annoyed when the above steps take longer than one tenth of a second. But now at least I have some documentation to look at, while waiting the remaining fractions of a second before the page renders.</p>
<p><a href="http://www.flickr.com/photos/amboo213/115034446/sizes/s/"><img class="alignnone" title="Spoiled dog - by amboo213 on Flickr" src="http://farm1.static.flickr.com/45/115034446_8bf43c2273_m.jpg" alt="Spoiled dog" width="240" height="180" /></a></p>
<p>Spoiled we are, all of us.</p>
<p><em>(Feel free to add more steps, through the comments…)</em></p>
Position: fixed CSS templates2009-12-31T15:14:26+01:002009-12-31T15:14:26+01:00http://friendlybit.com/css/position-fixed-css-templates/Emil StenströmIn 2006 I wrote an article about simulating Frames and Iframes and from time to time, I get questions of how to make modifications to the templates...
<p>In 2006 I wrote an article about <a href="/css/frames-or-iframes-with-css/">simulating Frames and Iframes</a> and from time to time, I get questions of how to make modifications to the templates presented. But one big thing has changed since 2006: <strong>Perfect support for IE6 is no longer mandatory</strong>.</p>
<p>So yesterday, when Brandon Cobb of <a href="http://superfighter.com/">Super Fighter Team</a> asked about a design with a fixed header, fixed left column, and scrolling right column, I thought I'd renew my take on <a href="/css/frames-or-iframes-with-css/">simulating frames</a> with CSS (The original article is still good for background information, so I still recommend reading it).</p>
<h2 id="position-fixed-css-templates">Position: fixed CSS templates<a href="#position-fixed-css-templates">#</a></h2>
<p>The idea is this: Instead of specifying what parts of the page should scroll, we can <strong>specify what parts should stay fixed when scrolling</strong>. This makes it easier to deal with several fixed parts of the same layout, but also allows us do to things frames cannot do.</p>
<p>So what's the trick? Well, <code>position: fixed</code> does exactly what we want. It works just like <code>position: absolute</code>, but it stays still when the page is scrolled. So it's really just a matter of making sure things don't overlap.</p>
<ul>
<li><a href="/files/fixed/fixedtopandleft.html" data-no-instant>Demo: Fixed top, fixed left, scrolling right</a></li>
<li><a href="/files/fixed/fixedtop.html" data-no-instant>Demo: Fixed top, scrolling bottom</a></li>
<li><a href="/files/fixed/fixedleft.html" data-no-instant>Demo: Fixed left, scrolling right</a></li>
</ul>
<p><strong>Try resizing the page, and see how the scrolling works</strong>. The templates have been tested in: Fx 3.5, IE8, IE7, IE6 (see note below), Opera 10, Safari 4; all on Windows. Let me know if you can test it on more browsers, or find bugs.</p>
<p>You're of course free to use this templates as you see fit, with or without a link back, commercially or not. Consider it public domain.</p>
<h2 id="fixes-for-ie6">Fixes for IE6<a href="#fixes-for-ie6">#</a></h2>
<p>As I've said, these designs don't act the same in IE6. Instead of some parts being fixed, the whole page scrolls in IE6. The good thing about this is that <strong>IE6 users won't see that your site is "broken"</strong>, they will just get another design. And as the number of IE6 users goes towards zero, your design will be more and more consistent :). The fallback is very simple, IE6 gets <code>position: absolute</code> instead of fixed, using the <a href="http://www.webdevout.net/css-hacks#in_css-important">!important hack</a> (you should probably use <a href="http://www.quirksmode.org/css/condcom.html">conditional comments</a> instead).</p>
<p>Hope these templates are useful for some of you!</p>
Google support gone wrong2009-10-24T15:00:28+02:002009-10-24T15:00:28+02:00http://friendlybit.com/other/google-support-gone-wrong/Emil StenströmGoogle really produces great software. I use many of them: Web Search, Picasa, Reader, Feedburner, Analytics, Images, Groups, Docs, Translate, Code, Chrome,...
<p>Google really produces great software. I use many of them: Web Search, Picasa, Reader, Feedburner, Analytics, Images, Groups, Docs, Translate, Code, Chrome, Maps, Video, Blog Search, Youtube, AJAX API, Webmaster Central, and Site Search.</p>
<p>Just to name a few :)</p>
<p>Problem is, with many of the above, if something breaks you're out of luck. Because it's <strong>god damn impossible</strong> to get a hold of someone that you can talk to. Do you reach anyone at Google with your e-mails? Does anyone from Google read your forum posts? Highly unlikely.</p>
<p>Google is a great example of support gone wrong. I think the explanation is easy: Few of the programmers I know want to deal with support. They want to deal with coding! And since Google is a company of programmers, it doesn't want to do support.</p>
<p>Let me tell two stories:</p>
<h2 id="feedburner">Feedburner<a href="#feedburner">#</a></h2>
<p>Feedburner once was a great company, with a simple but thought out service. They gave you subscriber statistics of your RSS feed. You just redirected your feed to them, and made all your subscribers sign up to their generated feed, and they did all the tricky calculations. Simple, efficient.</p>
<p>As a company Feedburner understood the value of being personal. Messages throughout the site stated "My feeds like a little namespace to call their own", "Sometimes your feed just wants to look good. Spruce it up in the following ways", "Oh dear, what kind of trouble?". Nice personal touch :) Feedburner developers where easy to get in touch with, an e-mail and you had a friendly, knowledgeable person to talk to.</p>
<p>Then Google came along and bought the whole thing. Everything was rewritten to Google's platform, domains where switched, and chaos ensued. Of course, during that time, Feedburner's previous support people totally vanished, and everyone was directed to the Feedburner Status Blog, when you could confirm they where <strong>not</strong> working on your problem. Just great.</p>
<p>For three weeks now, my subscriber stats have jumped from 800 to 3000, back an forth, several times per week. Nice, isn't it?</p>
<img class="alignnone size-full wp-image-567" title="feedburner_stats" src="/files/post-media/feedburner_stats.PNG" alt="feedburner_stats" width="519" height="165">
<p>Feedburner is apparently broken, and the simple service of delivering feed statistics doesn't work.</p>
<p>So I <a href="http://groups.google.com/group/feedburner-statistics/browse_thread/thread/3989f82b9efc3b26/e0990145155dca15?lnk=gst&q=subscriber&pli=1">post to their Google Group</a>, the place where you should ask questions about the service. Three months later, several other users have reported having the same problem, but no reply from a Feedburner developer.</p>
<p>Now I'm thinking of switching. Anyone have a good alternative ready?</p>
<h2 id="google-wave">Google Wave<a href="#google-wave">#</a></h2>
<p>Services that start at Google are even less likely, compared to acquired services like Feedburner, to have proper support. It's just not a priority, and there's far too many interesting programming challenges to deal with users.</p>
<p>So when Wave gives me an old picasa name as my username (<code>[company name].|place of one of our conferences]@googlewave.com</code>), I know there's very little chance that I'll get help from anywhere. The official channel to ask for help is their support forum, but it doesn't seem that they reply to issues there. <a href="http://www.google.com/support/forum/p/wave/thread?tid=6cb8ca45d22453e5&hl=en">My message there from two weeks ago</a> stands on it's own, with no replies.</p>
<p>It's the proposed revolution that will replace e-mail, and I can't use it :(</p>
<h2 id="bad-trend">Bad trend<a href="#bad-trend">#</a></h2>
<p>This trend of Google not offering even basic support from dedicated people is a unfortunate development, that should be taken seriously by executives at Google, and dealt with at a very high level.</p>
<p>Launching new web services is easy, improving a services based on feedback is much harder. Google has not yet managed to crack that nut.</p>
Google Chrome as an Internet Explorer plugin2009-09-23T16:15:49+02:002009-09-23T16:15:49+02:00http://friendlybit.com/browsers/google-chrome-as-an-internet-explorer-plugin/Emil StenströmI just encountered a quite mindboggling piece of news on the Google Wave blog. It seems they have decided not to support Internet Explorer at all. Not IE6,...
<p>I just encountered a quite mindboggling piece of news on the Google Wave blog. It seems they have decided <strong>not to support Internet Explorer at all</strong>. Not IE6, IE7 or IE8. Surprised? I sure was. What's even better is that to still give these users the opportunity to use Google Wave, they've built a plugin for Internet Explorer, that loads the <a href="http://googlewavedev.blogspot.com/2009/09/google-wave-in-internet-explorer.html">Chrome browser with Google Wave inside it</a>.</p>
<p><strong>What?</strong> Load a browser as a plugin inside another one? I guess this is a real war after all? Who will build the first browser to load Firefox into Chrome? Internet Explorer inside Firefox?</p>
<p><strong>Why?</strong> Well, now they don't have to care about Internet Explorer support at all. Felt that heavy weight lift from your shoulders? Suddenly large parts of HTML5, CSS3, and modern javascript, is available to them, with no backporting and performance tuning needed. Must be fabulous.</p>
<p>Now. Combine that with the possibility for the developer to <a href="http://blog.chromium.org/2009/09/introducing-google-chrome-frame.html">choose when to trigger the different browsers</a>. We're up for a whole new ride. You're invited.</p>
SpriteMe – Combine images and get fewer HTTP requests2009-09-19T17:09:02+02:002009-09-19T17:09:02+02:00http://friendlybit.com/css/spriteme-combine-images-and-get-fewer-http-requests/Emil StenströmThose of you that care about website performance have probably read about combining images, something that's called "CSS sprites". The idea is that by using...
<p>Those of you that care about website performance have probably read about combining images, something that's called "CSS sprites". The idea is that by using the same (somewhat larger) image several times, you get fewer HTTP requests to your site, and therefore speed it up. Problem is, most of your images are CSS background images, that are positioned using clever background-positions and repeats.</p>
<p>Now, this makes to tricky to combine images. Something that repeats horizontally can't be combined with something that repeats vertically (unless there's transparency involved), and wide images can't be combined with narrow ones. So combining is usually tedious, manual work, both to combine the images and then calculate the new background-positions required.</p>
<p>Lucky for us then, that there is a tool called <a href="http://spriteme.org/">SpriteMe</a>, available as a bookmarklet (a bookmark containing javascript), and as an excellent <a href="http://spriteme.org/demo.php">online demo</a> that walks you through how it works. SpriteMe does all the hard work for you, you just have to copy and paste both the combined images, and the new background rules, to your site.</p>
<p>Decreasing the number of HTTP requests have never been simpler. Well done <a href="http://www.stevesouders.com/">Steve Souders</a>!</p>
Voddler – movie streaming for the masses?2009-08-31T00:12:46+02:002009-08-31T00:12:46+02:00http://friendlybit.com/other/voddler-movie-streaming-for-the-masses/Emil StenströmI've recently managed to get a hold of a beta invite to Voddler, and thought I should tell you a little about my experience of it. But first, big thanks to...
<p>I've recently managed to get a hold of a beta invite to <a href="http://www.voddler.com/">Voddler</a>, and thought I should tell you a little about my experience of it. But first, big thanks to <a href="http://twitter.com/GunnarBark">Gunnar Bark</a> (Tweets in Swedish, follow him!) who tipped me off about a Voddler invitation competition. It was run by Christian Rudolf at <a href="http://www.mjukvara.se/blogg/">mjukvara.se</a> (In Swedish, but definitely something to add to your feeds) who had 15 invites to give away.</p>
<p>Anyway.</p>
<p>Two years ago, <a href="/other/spotify-is-a-lot-like/">I got to test Spotify</a>, a music streaming that will soon launch in the US and is heavily anticipated. It completely changed how I listened to music, I deleted all my mp3:s and is now streaming all my music. <a href="http://www.voddler.com/">Voddler</a> is a similar streaming service, but for movies.</p>
<p>So, what do I think of it?</p>
<p>First of all, Voddler is in a very early phase of testing. It's what I would call a "<strong>real beta</strong>", where the client crashes frequently, subtitles sometimes lag behind, the interface is tricky to use, and several features just don't work.</p>
<p>Thing is, I'm quite certain Voddler will <strong>revolutionize how I watch movies</strong>, anyway. Because at the core of Voddler is HD-quality streaming, that just works. Believe me, I normally don't watch that many movies, but have seen <strong>four</strong>, ****in the last 48 hours. They are just a couple of clicks away, and start in 10 seconds (during which you'll watch a commercial). Here's some <a href="http://pappmaskin.no/2009/07/voddler-screenshots-and-details/">screenshots</a>.</p>
<p>Now. I'm saying that the client is a beta, and that there are serious bugs left, what kind of bugs do I mean?</p>
<ul>
<li>About half of the <strong>menu options don't work</strong>. "Tv series" lead nowhere, I can't browse movies by actor, director, studio, and several genres are empty. In my opinion, they would gain a lot by just <strong>removing those options until they lead somewhere</strong>! This is a no-brainer.</li>
<li>The <strong>client freezes and crashes</strong> regularly, and I have never been able to watch two movies in a row without restarting in between. This of course requires squashing bugs that are left in the code, and <strong>improve the testing procedure</strong>, so that such bugs never reach production code. Using mozilla-style reporting that allow people to <strong>send in crash reports</strong> is probably a good idea at this stage. The code is based on <a href="http://en.wikipedia.org/wiki/XBMC">XBMC</a>, and people say stuff like "how could they add that many bugs to a product that good?!". Voddler, don't make it that easy to dismiss your hard work!</li>
<li>Sometimes the <strong>subtitles skip some lines</strong>. I watched <a href="http://www.imdb.com/title/tt0325005/">Antikiller</a>, a russian action movie, five times important lines were shown only half a second on the screen, making me miss important pieces of the story. I'm not sure if this had something to do with the subtitles for that exact movie, or lag because of Voddler, but I know that it was a crappy first impression of the client. It just has to be fixed.</li>
<li>The <strong>support forum is so slow it's unusable</strong>. My guess is that it's on the same network as the movie streaming service, and therefore goes down together with that one. Those two just <strong>have to</strong> be independent, as you need the forum most when the other is down.</li>
<li>The <strong>UI doesn't work usability-wise</strong>. First of all, it's built for television sets, which means that only the keyboard works (arrow keys, space and esc), no mouse support. Several of the menues cycle (when you're on the end the first item appears again), so you'll easily loose track of where you are. There are small errors all over the place, things that makes finding and starting movies difficult.</li>
</ul>
<p>So, in summary, the core of Voddler is good, but the interface needs quite a lot of work before it can be released to the public. No matter what, I'll keep following the development of this product!</p>
<p>In general, it seems that when you Americans stop us from using your servies (ie. <a href="http://www.voddler.com">Hulu</a>), we Swedes build our own services. First Spotify, now Voddler.</p>
Techniques to use when IE6 dies2009-08-26T23:54:51+02:002009-08-26T23:54:51+02:00http://friendlybit.com/css/techniques-to-use-when-ie6-dies/Emil StenströmEveryone except Microsoft themselves are talking about the death of IE6. I've tried motivating people to drop support, arguing that you at least can show...
<p>Everyone <a href="http://www.eweek.com/c/a/Windows/Microsoft-Internet-Explorer-6-Support-Continues-Despite-Calls-for-PhaseOut-307122/">except Microsoft themselves</a> are talking about the death of IE6. I've tried <a href="/browsers/motivation-for-building-for-ie6/">motivating people to drop support</a>, arguing that you at least can show IE6 users a message. Many have replied with "but our IT department doesn't let us…", and I can say nothing more than that the IT department is filled with humans. Which means they are lazy, and upgrade when people whine enough about it. It's a shame it has to be that way, that we have to <a href="http://www.ie6nomore.com/corporate-users.html">punish people for their IT departments</a>, but that's how it has to be.</p>
<p>As <strong>web developers</strong>, we should be the ones complaining the loudest. We have so much to win on IE6:s death it's silly. Just look at the below list of things IE6 can't do, but IE7 can (the next worst browser):</p>
<ul>
<li>Native PNG alpha transparency without silly hacks.</li>
<li>Several selectors: Child selector (">"), Adjacent sibling selector ("+"), Attribute selectors ([attr=value]), and <a href="http://www.w3.org/TR/css3-selectors/#general-sibling-combinators">General sibling selector</a> ("~", CSS3)</li>
<li>Min-height, Max-height, Min-width, Max-width</li>
<li>Multiple class/id selectors in the same ruleset (ie. .class1.class2 { … })</li>
<li>:hover on all elements, not just links</li>
<li>position: fixed</li>
<li>Native XMLHTTP (Without ActiveX)</li>
<li>International Domain Names (IDN), the ability to use UTF-8 chars in domains</li>
<li>Page zoom that zooms the whole page (don't worry about zoom)</li>
</ul>
<p>This is a huge step forward for us web developers. Huge! Bigger then when CSS3 comes out, because we won't be able to use that one for years. Someone is pushing the front of what's possible, I'm pushing for the front of what's <strong>usable</strong>.</p>
<p>What can you do to help me get everything in the above list? And, did I forget something?</p>
<p>Sources:</p>
<ul>
<li><a href="http://www.quirksmode.org/css/contents.html">CSS Compatibility charts</a></li>
<li><a href="http://blogulate.com/content/new-features-of-internet-explorer-7/">IE6 vs IE7 - New features in Internet Explorer 7</a></li>
</ul>
Tapestry 5, and how not to treat HTML2009-07-23T21:39:10+02:002009-07-23T21:39:10+02:00http://friendlybit.com/html/tapestry-5-and-how-not-to-treat-html/Emil StenströmI've previously written about how Microsoft Sharepoint mistreats HTML, and makes it look a whole other language. But truth to be told, Sharepoint (and .NET...
<p>I've previously written about how <a href="/html/default-html-in-sharepoint-2007/">Microsoft Sharepoint</a> mistreats HTML, and makes it look a whole other language. But truth to be told, Sharepoint (and .NET for that matter) isn't the only framework that can't handle HTML. I've recently worked with a Java framework called <a href="http://tapestry.apache.org/">Tapestry 5</a>, and it's really bad in some respects too (though not quite as bad as Sharepoint). Note that this is a review based on <strong>only</strong> how it handles HTML, not any other of its merits. Let's get started.</p>
<p>Many of Tapestry's problems comes from their design decision to parse the HTML you're trying to output. Yes, Tapestry parses your HTML, and adds stuff to it dynamically. This is nothing new, anyone that has played with ASP.NET knows how hidden form elements get stuffed in here and there. This is a nightmare for an interface developer, we need exact control over HTML to do our jobs well.</p>
<p>Tapestry does horrible things to HTML:</p>
<ul>
<li><strong>Several extra javascripts and CSS files</strong> are referenced in the head tag. There is no simple way to get rid of these.</li>
<li><strong>A meta tag</strong> which states that the tapestry did generate this page, is added.</li>
<li>The two above are added to the head, and if a <strong>head tag doesn't exist, it gets added</strong>. Never mind that your current little HTML snippet was just a little part of a page, that was being fetched with AJAX, Tapestry will add a head tag for you.</li>
<li><strong>More javascript, and a hidden div</strong> with a firebug-like console, is appended to the end of the body element.</li>
<li><strong>Self-closing tags are expanded</strong> to a start tag and an end tag (<code><input /></code> gets transformed to <code><input></input></code>), which means you can't use XHTML together with Tapestry.</li>
<li><strong>All whitespace is removed</strong> by default, and you have to disable the "feature" on a tag-by-tag basis ("Please don't strip whitespace inside this list, IE6 goes crazy then"). This is a mess for interface developers, who know that whitespace matters for rendering. It was even <a href="https://issues.apache.org/jira/browse/TAPESTRY-2028">pointed out to Tapestry developers</a> early on, but was ignored.</li>
<li>There are ways to do loops, if:s, reference variables and generate URL:s, but all of these are based on the HTML parsing. And as a good parser, <strong>it skips all comments</strong>. This means using tapestry template code inside a HTML comment will not work. When do you need that? Conditional comments! So what if you want an URL generated to your IE6 stylesheet? No go. You'll have to write a custom component that does that for you.</li>
<li>Changes the <strong>id of all your forms to "form" and adds name="form"</strong> (which is invalid HTML).</li>
<li>Adds a <strong>hidden "t:formdata" field to forms</strong>, much like the dreaded ASP.NET viewstate.</li>
<li>One of the javascript files added is <a href="http://www.prototypejs.org/">prototype</a>, a javascript framework which isn't compatible with jQuery. So you have to rewrite your javascript code to work in "No conflicts mode" if you want it to work with Tapestry.</li>
</ul>
<p>No. Tapestry was clearly not built with an interface developer in mind. Why is it so hard for many web framework developers to just talk with people that work with HTML, CSS, and Javascript? Please ask us <strong>before</strong> implementing stuff like the above. We'll gladly give you our viewpoint.</p>
Make a div clickable2009-06-30T22:53:25+02:002009-06-30T22:53:25+02:00http://friendlybit.com/js/make-a-div-clickable/Emil StenströmWe all dislike that links are so small, and hard to click. So of course we want to make the clickable areas bigger. Some would think that doing this with...
<p>We all dislike that links are so small, and hard to click. So of course we want to make the clickable areas bigger. Some would think that doing this with some CSS on the a-tag would be a good way, but then you can't have block level elements inside it (you'll get a validation error if you try to put headings or paragraph tags inside of links). So what's a more general solution?</p>
<p>My take is to use a div instead, and use javascript, of course together with a good fallback. When clicking the div, find the first link inside it, and go to that URL. It's simple, and with a few additional quirks, it gets really useful.</p>
<p>Javascript code (requires jQuery):</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">block</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">(</span><span class="s2">".teaser"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">block</span><span class="p">.</span><span class="nx">click</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s2">"a:first"</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"href"</span><span class="p">)</span>
<span class="w"> </span><span class="p">});</span>
<span class="w"> </span><span class="nx">block</span><span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">"clickable"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">block</span><span class="p">.</span><span class="nx">hover</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s2">"a:first"</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"href"</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="kd">function</span><span class="p">(){</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span>
<span class="w"> </span><span class="p">})</span>
<span class="p">});</span>
</pre></div>
<p>CSS for showing that the div actually is clickable:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">.</span><span class="nc">clickable</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">cursor</span><span class="p">:</span><span class="w"> </span><span class="kc">pointer</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">clickable</span><span class="p">:</span><span class="nd">hover</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#efefef</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>A <a href="/files/clickable_block/" data-no-instant>clickable div demo</a> is of course available.</p>
<h2 id="how-it-works">How it works<a href="#how-it-works">#</a></h2>
<ul>
<li>When the div (or other tag, you choose) is clicked, find the <strong>first anchor tag</strong>, get it's href attribute, and go there. Relying on an actual link means you always have a fallback, so no cheating.</li>
<li>When <strong>javascript is disabled</strong>, it just falls back to a regular block, where only the links are clickable.</li>
<li>A class called "clickable" is set on the block to allow for <strong>javascript-specific styling</strong>, such as changing the cursor with cursor: pointer, something you don't want to happen when the block isn't clickable.</li>
<li>The changing background color on <strong>hover is done with CSS</strong>, which I think is fair, considering the small percentage of users using IE6. Changing background color isn't a must feature.</li>
<li>Lastly, since we're simulating a link here, it should show where the link is going. I've done this by setting the statusbar to the link location on hover, something that's useful when it works (users can disable this in some browsers).</li>
</ul>
<p>Hope that little snippet is useful for someone out there, I think it's a good example of good use of javascript.</p>
Why people skip newspapers and read news on the web instead2009-06-25T22:44:12+02:002009-06-25T22:44:12+02:00http://friendlybit.com/modern-web/why-people-skip-newspapers-and-read-news-on-the-web-instead/Emil StenströmYou can't be involved with what's happening on the internet without coming in contact with the "newspaper crisis" somehow. From a business perspective it's...
<p>You can't be involved with what's happening on the internet without coming in contact with the "newspaper crisis" somehow. From a business perspective it's simple really: Much fewer people buy newspapers (on paper) nowadays. Please note that this has very little to do with advertisement or business models, I'm talking about newspapers from the user perspective here.</p>
<p>Internet is really a commodity nowadays. People process loads of information on the web every day, and this of course affects how they expect newspapers to behave. Every time I hold a big newspaper in my hands I'm surprised at how inferior it is compared to reading news on the web.</p>
<h2 id="newspapers-have-problems-with-references">Newspapers have problems with references<a href="#newspapers-have-problems-with-references">#</a></h2>
<p>If I find an interesting news story on the front page, it's a mess finding the full article in there. The references are done with page numbers, but with page numbers that are local to a certain part of the paper. "Culture, page 7". And the culture part is stacked inside the part I'm reading, so I first have to find that one, then find the page numbers (which are removed from pages with ads), and then finally find the article I wanted.</p>
<p>The same is true for related articles. If I read an article I like, it's quite likely that I want to read other articles on the same subject. Newspapers solve this today by placing similar articles close to each other, and hope that you see them. This is of course limited, and gets harder when pages sizes shrink.</p>
<p>Compare this with clicking a link on the web. If I find an interesting article teaser, I click it, and am instantly taken to the full article. If that article was indeed as interesting as the teaser suggested, I'm often presented with similar articles, from similar categories, and can click them to move there.</p>
<h2 id="newspapers-are-slow">Newspapers are slow<a href="#newspapers-are-slow">#</a></h2>
<p>Even the most frequently published papers are only distributed once per day. This simply means that papers can't compete on speed, being first with a certain story. Even if you happen to get your hands on a story at the perfect time, a paper still have to be both printed, and distributed to people. This takes hours.</p>
<p>What's worse, morning newspapers brand themselves as dealing with "today's news", when in fact it's the news from yesterday. This hasn't been a problem before, since there was no faster way to get news. Now there is.</p>
<p>If speed is important to you, you can easily subscribe to news via e-mail, Twitter or RSS, and be instantly updated.</p>
<h2 id="newspapers-are-static">Newspapers are static<a href="#newspapers-are-static">#</a></h2>
<p>Articles in a newspaper are, once published, not possible to update and improve. They are left for the wind, even though there are inaccuracies or important clarifications to be made. Any conversation sparked won't be there.</p>
<p>This is of course the strongest argument for internet news. A big article will be different if you look at it later the same day. Comments and updates based on feedback are able to improve articles considerably.</p>
<h2 id="newspapers-dont-have-enough-unique-content">Newspapers don't have enough unique content<a href="#newspapers-dont-have-enough-unique-content">#</a></h2>
<p>Big parts of daily newspapers contain poor rewrites, or plain copies, of articles from elsewhere. The reasoning is probably that they are trying to be exhaustive, give a broad view of what has happened. Problem is, they are hiding their own unique content behind loads of reposts of other's content.</p>
<p>The same happens on the web, but instead of copying the article you link to it. Then you get to read the news from the real source, and dig in deeper if you want to. Additionally, there's safegards that stop people from copying other people's content. For instance, Google have special filters for filtering out duplicate content.</p>
<h2 id="newspapers-are-not-relevant-enough">Newspapers are not relevant enough<a href="#newspapers-are-not-relevant-enough">#</a></h2>
<p>The biggest reason why I don't subscribe to any newspapers is that they are not relevant enough. I'm not one bit interested in sports, and still, during big sporting events newspapers push them to the front page, over interesting internet-related news; things I find interesting.</p>
<p>The key here is of course to realize that relevancy is in the eye of the beholder. Only <em>I</em> know what I find interesting, and relevant. Why trust someone else's relevancy ranking when I can easily get my own ranking online? Even if I don't want to tailor-pick RSS feeds and build my own custom news feed, there's someone out there that has more similar taste than the four major newspapers here.</p>
<h2 id="so-what-should-newspapers-do">So, what should newspapers do?<a href="#so-what-should-newspapers-do">#</a></h2>
<p>Well, they have two options: <strong>One</strong>, they could keep writing articles, hoping that the quality will be high enough to turn the trend, or <strong>Two</strong>, they could start thinking of <strong>how</strong> they deliver news. The expectation of how news should be served is changing. It now needs to be delivered…</p>
<ol>
<li>… filled with references for digging deeper</li>
<li>… faster than once a day</li>
<li>… in a manner where people's contributions enhance it</li>
<li>… with a quality stamp that ensures that you're reading something you couldn't get anywhere else</li>
<li>… personalized to my own specific taste. No sports.</li>
</ol>
<p>Is there any other way to do this than focusing aggressively on the web, and less on dead trees?</p>
Custom fonts using Cufón2009-05-08T20:20:17+02:002009-05-08T20:20:17+02:00http://friendlybit.com/browsers/custom-fonts-using-cufon/Emil StenströmIf you've worked with webdev professionally you know how it goes. "Why can't a company with a strong visual brand get to use their own font?", the designer...
<p>If you've worked with webdev professionally you know how it goes. "Why can't a company with a strong visual brand get to use their own font?", the designer asks. Then a long discussion about web fonts follow, where you decide to replace the font with a "web safe" font instead. Or do you?</p>
<p>You could think it's strange that in 2009, we can't use any fonts we want on the web, and I would fully agree. You could ask whose fault that is, and I would reply with a quote from a <a href="http://www.w3.org/Fonts/Misc/minutes-2008-10">meeting between browser makers in august 2008</a>:</p>
<blockquote>
<p>"My understanding, from Chris, is that supporting direct linking of the fonts would be a great disservice to the independent font industry. <strong>A high-level decision within MS</strong> says we won't implement that in IE. So what is done other than EOT is [probably] not going to interop with IE. "</p>
</blockquote>
<p>"MS" is of course Microsoft, and "Chris", is referring to Chris Wilson, Platform Architect of the Internet Explorer Platform team. The same Chris has also written a <a href="http://cwilso.com/2008/07/23/fonts-embedding-vs-linking/">longer text about font linking</a> on his blog. I first thought that this was something the font foundries had pushed through, but on the above post it seems that this is also a personal opinion. Browsers (but only IE) need to protect fonts from getting pirated.</p>
<p>And that's the whole reason why we don't have cross-browser fonts on the web today. (Although direct linking to fonts work in all the latest versions of Firefox, Opera, and Safari). Nice isn't it?</p>
<h2 id="embedding-fonts-anyway">Embedding fonts anyway<a href="#embedding-fonts-anyway">#</a></h2>
<p>Of course, there's still a need to embed custom fonts on webpages. That means clever developers will develop techniques will work around a broken internet explorer. No matter what the font founderies and Internet Explorer team thinks.</p>
<p>My reasoning for why this is a good thing is because that's how everything else works in the browser. Even though anyone can copy an image, we have a big market for stock images. Even though anyone can copy the HTML, CSS, and Javascript of a whole site, we still have people building websites for money. <strong>Fonts are no different</strong>, and the exact same business model that works for stock images can work for fonts.</p>
<p>***</p>
<p>One popular technique is sIFR, a way to use javascript to replace regular html with flash. Inside the flash you embed the font you want, and voilá, you can use any font you want. sIFR misses one crucial point though: It's far too annoying to embed a font inside a flash movie. You need a commercial program, and you need to know what you're doing. And you're dependent on flash support. It's not that bad, but a bit annoying to work with.</p>
<p>So for a recent project I've been playing with <a href="http://wiki.github.com/sorccu/cufon/about">Cufón</a>, which uses javascript, but draws on canvas, or in VML for browsers that don't support canvas (IE). They have an extremely friendly website, which walks you through the process of getting things to work, and the font conversion needed is available directly on the website. I've only used it for simple cases, but it works really well.</p>
<p>All in all, Cufón is a great alternative until IE gets its shit together.</p>
<p>PS. Famous people that don't agree with me:</p>
<ul>
<li><a href="http://clagnut.com/">Richard Rutter</a>, author of the clagnut blog suggests that font founderies <a href="http://clagnut.com/blog/2166/">server-side generate our fonts on demand</a>, much like Google Maps only sends a part of the map, and not all of it.</li>
<li><a href="http://joeclark.org/">Joe Clark</a>: "Quite simply, there is <a href="http://blog.fawny.org/2008/07/22/billhillsite/">no broad clamour</a> among Web <em>designers</em> to use any font they want."</li>
<li><a href="http://jasonsantamaria.com/">Jason Santa Maria</a>: "embedding normal typefaces without any sort of precautions is putting it on a silver platter for anyone to take freely. That’s like saying people steal from stores anyway, so let’s just leave the doors unlocked at night :)"</li>
<li>And of course, the IE team…</li>
<li>…and all the typeface makers in the world.</li>
</ul>
Projectors: a great accessibility argument2009-04-03T17:31:32+02:002009-04-03T17:31:32+02:00http://friendlybit.com/accessibility/projectors-a-great-accessibility-argument/Emil StenströmSo there I sat, at the demonstration of a new website I've been part of building. About 10 people in the room, some of which had never seen the site before....
<p>So there I sat, at the demonstration of a new website I've been part of building. About 10 people in the room, some of which had never seen the site before. There had been preparations, and we had gone through which parts of the site we were going to present. Only the simple part left…</p>
<p>So the presenter fires up the projector, connects it to his Mac, and looks at the projection. Half the site is outside of the screen. Turns out the maximum resolution is 800×600, and we've designed the site for 1024! People started looking at each other.</p>
<blockquote>
<p>"We have to be able to show the site with a projector!", one from the audience proclaimed.</p>
</blockquote>
<p>Awkward silence.</p>
<p><img class="secondary" src="http://farm1.static.flickr.com/34/110679756_98fdd45346.jpg?v=0" alt="" width="180" height="175" /></p>
<p>I've rarely heard people working with accessibility mention projectors as arguments for accessibility, but it turns out they are great for that purpose. Just look at it like this:</p>
<ul>
<li><strong>Resolution</strong> is often at the very low end, and they get upgraded much slower than regular computers.</li>
<li><strong>Brightness</strong> is much lower than on a computer screen, especially at daytime, in a room with bad curtains.</li>
<li>Many presenters <strong>move their mouse</strong> by looking at the projection, which makes clicking things harder.</li>
</ul>
<p>Interesting isn't it? Those three just happens to be exactly the same things that we try to optimize when working with accessibility:</p>
<ul>
<li>We try to avoid having people to <strong>scroll sideways</strong>, because unexperienced users find that hard to do. A flexible design, that can adapt to different screen widths (within reason), is a great way to accomplish that.</li>
<li>We work hard to make sure that the contrast between page elements is big enough. That way, the large part of the population with low vision (don't forget those that left their glasses at home…), can use the page without problems.</li>
<li>We expand clickable areas of links and buttons, to make sure people with motor disabilities can still use our site.</li>
</ul>
<p>So, we could just as well have been optimizing the "projector experience" all along.</p>
<p>How did the presentation go? Well, we simply zoomed the site out one step, and continued as usual. You are making sure your site zooms properly are you?</p>
Usability isn’t a crime2009-03-01T21:00:27+01:002009-03-01T21:00:27+01:00http://friendlybit.com/other/usability-isnt-a-crime/Emil StenströmThe programmers behind The Pirate Bay are getting charged with making it easy to share files over the BitTorrent protocol. Note that it's not because...
<p>The programmers behind <a href="http://thepiratebay.org/">The Pirate Bay</a> are getting charged with making it easy to share files over the BitTorrent protocol. Note that it's not because they've done it themselves, but because they have made it easier for others. Never before has <strong>usability been a crime</strong>.</p>
<h2 id="quotthey-have-to-get-paidquot">"They have to get paid"<a href="#quotthey-have-to-get-paidquot">#</a></h2>
<p>Copyright holders protest and say that they "have to" get paid for what they produce. And that argument seems to work well with people, because hey, why shouldn't they? (Real non-geeky people, not people like you).</p>
<p>At the same time, people seem to agree that there are exceptions. It is considered OK to play music to your friends. Or lending a CD to a friend over the weekend. Or letting a colleague listen to some music on your iPod. So sharing with friends is fine. The problem, and the major change that many have missed, is that <strong>people have more friends</strong> than ever before. All across to globe, all connected via the interwebs. And as the number of friends grow, people tend to shift over, and not consider it OK to share any longer. "Hey, you can't share with 100 people! The artists have to get paid!".</p>
<h2 id="lets-make-some-laws">Lets make some laws<a href="#lets-make-some-laws">#</a></h2>
<p>So lets say you want to make laws based on that kind of "reasonable sharing". How would you do that? Do you <strong>lawfully define what a friend is</strong>? The number of friends a person is allowed to have? That you have to keep a count of how many times you let someone listen to your iPod? No, it just doesn't work.</p>
<p>Perhaps if you put a ban on some types of technology. Technology that makes it easy to share to many? No, because technology moves several magnitudes faster then laws get made, so as soon as you manage to ban one technology, there are five new ones available that circumvent your law. <strong>Allow any form of sharing and technology will generalize it to be used for mass sharing</strong>. (See OneSwarm for an example).</p>
<p>What about using technology to block sharing? This is what's called DRM, Digital Rights Management. Sorry, <a href="http://www.craphound.com/msftdrm.txt">it just doesn't work</a>. Every DRM system ever built, has been broken. The core problem is: it's not possible to both block people from sharing music, and let people listen to it.</p>
<h2 id="quothmm-then-maybe-allow-no-sharingquot">"Hmm, then maybe allow no sharing?"<a href="#quothmm-then-maybe-allow-no-sharingquot">#</a></h2>
<p>So what about banning sharing altogether, strange as it may seem? Well, paying customers would hate it. A big part of music is sharing it with people, hoping that they will like what you like. We want to play music at our parties, without requiring everyone to pay a license fee to attend. A complete ban (and extensive citizen surveillance to go with it) would quickly lead to a separation between music that we can share, and music we can't share.</p>
<p>This is exactly what has happened with computer programs. There's now <strong>proprietary and open source</strong>, <strong>no-share and please-share</strong>. Open source is growing stronger every day, and lots of companies decide to join the tide, and release their code the same way. This is exactly what will happen to music. Let's call it the <strong>Open Music</strong> movement, and lets see how many years the no-share music will last.</p>
<h2 id="sharing-is-nothing-strange">Sharing is nothing strange<a href="#sharing-is-nothing-strange">#</a></h2>
<p>To explain why allowing people to share isn't so strange, compare a <strong>famous book author</strong> to a <strong>famous speaker</strong>. People tend to think that writers must get paid for what they write, once every time someone reads their text. If lots of people read what they write, they somehow "are entitled to" lots of money.</p>
<p>Speakers on the other hand, get paid each time they speak. Not each time someone listens to a recording of their speech, or someone else repeats what they say, but based on their own performance, once. They get paid for original performance, not copying. This also means that <strong>speakers want their stuff to be spread as much as possible</strong>. Because for each copy, there's a potential new customer waiting to pay them to perform.</p>
<p>So why is it so strange to see the same model for writers? Writers that get paid for their performance when writing a book, not by the number of people that read it.</p>
<h2 id="separate-distribution-and-performance">Separate distribution and performance<a href="#separate-distribution-and-performance">#</a></h2>
<p>So we have to separate distribution from performance. Distribution is the reason that authors think they need the big companies. How else could they distribute their great performances to a large audience? Well, the internet. Yeye, but how can they distribute it and get paid? That's where things get interesting, because now we're talking about <strong>business models</strong>.</p>
<p>Media companies have had a distribution monopoly for a very long time. Now the internet threatens that monopoly, by making it easy for anyone to distribute anything, for free. This isn't going to change, no matter what kinds of laws that get pushed through. So how do you tackle that?</p>
<p>And that's the challenge that the record industry should put all their power towards. Think of speakers instead of writers, how do they get money? Think of how the <a href="http://www.ted.com">TED conference</a> makes lots of money off speakers. Think of how you can build technology to compete with BitTorrent, how to get people to pay for performance, not distribution. Think of how you can <strong>improve usability</strong>, something that's in a pretty bad state when it comes to BitTorrent.</p>
<h2 id="what-model-to-use-is-not-my-problem">What model to use is not my problem<a href="#what-model-to-use-is-not-my-problem">#</a></h2>
<p>Companies missing proper business models is not my problem. It isn't, and has never been, a government problem either. There's no reason to pass integrity limiting laws to help companies survive. There doesn't need to be completed alternatives waiting. That's their own problem to solve, and time will tell if they manage the switch before it's too late or not. I don't know.</p>
<p>Meanwhile the internet continues to evolve, while media companies try to fine the programmers behind The Pirate Bay…</p>
When web development was easy…2009-02-16T17:02:33+01:002009-02-16T17:02:33+01:00http://friendlybit.com/browsers/when-web-development-was-easy/Emil StenströmDo you remember the time when web development was easy? Right where it all started, when there was just one browser, and only one website existed? Things...
<p>Do you remember the time when web development was easy? Right where it all started, when there was just one browser, and <a href="http://www.w3.org/People/Berners-Lee/FAQ.html#Examples">only one website</a> existed?</p>
<p>Things changed. And now you can't trust anything any longer. Trust me, if you think you know how your site will be shown, you're wrong. Just consider the 10 major steps of "progress" we've made since then:</p>
<ol>
<li><strong>Browser widths</strong> stopped being predictable as soon as people stopped using maximized windows, and monitor sizes stopped being the same everywhere. People cling to their fixed 760px or 960px grids feverishly (yes, me too), dreaming that they are what people use.</li>
<li><strong>Browser heights</strong> started giving us the same problems as widths, but toolbars also started showing up, making height prediction plain impossible to predict. "The fold" is now the top 10 pixels of a page, unless you got a browser warning, then "the fold" is pixels 10 to 20.</li>
<li><strong>Aspect ratio</strong>, the relation between width and height, went strange when first wide-screen monitors, then TV-screens and mobile phones, entered the market. I wouldn't be surprised if I'm soon able to set my own ratio, or if someone launches a stretchable screen that I can drag to my own preference. I hope your site is well prepared for that one.</li>
<li><strong>Colors</strong> differ not only depending on the lightning in the room (which was a problem as soon as there where two computers), but also depending on monitor (including brightness and contrast), gamma correction differences between operating systems, gamma correction bugs in PNG files and browser implementations, color profiles (now supported in Firefox 3.1!). Add to this accessibility tools that invert colors, increase or decrease saturation. Pantone color codes on the web anyone?</li>
<li><strong>Font selection</strong> is another interesting mess. The browser has a default font, different (of course), depending on what operating system/device you're on. The website author can try to override that font, specifying one or more fonts, which the user might, or might not, have. Oh, and lets not forget the editors, copying and pasting text from Outlook or Word, getting font tags inserted into your throughly crafted site.</li>
<li><strong>Font rendering</strong> complicates things even further by letting either the operating system or the browser render the fonts as they wish. Things like ClearType, subpixel font rendering, and font smoothing.</li>
<li><strong>Character encoding</strong> is far beyond repair, and this is easily conveyed by looking at what steps a browser has to go through to render a single letter. To <a href="http://blog.whatwg.org/the-road-to-html-5-character-encoding">quote Mark Pilgrim</a>: "It's a 7-step algorithm; step 4 has 2 sub-steps, the first of which has 7 branches, one of which has 8 sub-steps, one of which actually links to a separate algorithm that itself has 7 steps…".</li>
<li><strong>Unstyled HTML</strong> looks different because of default stylesheets in some (but not all) browsers. Developers are left guessing what styles to set to override all defaults.</li>
<li><strong>CSS styling</strong> is of course fully unpredicable, depending on not only browser, but on what underlying rendering engine, and version of that engine, and with what patches applied, and on what settings the user has made. On top of this we have piles of bugs, which tips most developers from scientists, trying to use logic to solve problems, to "empirates", trusting only trial-and-error as a tool to "just get it to work".</li>
<li><strong>HTML versions</strong> can also be selected in several ways, not always according to reason. First you can specify no doctype, and watch everyone try to render your site like IE5 once did, long time ago when someone used that browser. Then you can pick a doctype, and watch how some browsers render your page differently, depending on whether your doctype is in their "white-list" or not. And then there's standards mode, quirks mode, and almost standards mode, there's XML prologues and MIME-types, and what-not.</li>
</ol>
<h2 id="but-thats-not-all-enter-ie8">But that's not all, enter IE8<a href="#but-thats-not-all-enter-ie8">#</a></h2>
<p>The newest entry in the "making web development hard" toplist, is (soon to be released) IE8. They have recently decided that your page will be <a href="http://www.isolani.co.uk/blog/standards/Ie8BlacklistForcingStandardsRenderingOptIn"><strong>rendered based on popular vote</strong></a>. So better not make your designs "arty" in any way. People might think it's broken and vote you to IE7 rendering (very broken). <strong>Don't laugh</strong>, it's not a joke, the proof is on IEblog, linked in the paragraph above. I dare you.</p>
<p>"Are you fully out of your fucking mind?", you might be tempted to ask the IE8 developers. The reply is simply, no no, don't worry, just settings this HTTP header you can opt-out of the rendering that popular vote has selected for you, even though you already opted-in by setting a doctype once.</p>
<p>And so we slowly stop caring, and give up. Dreaming ourselves back to the time when there where one computer, and one website…</p>
A couple of sites I’ve launched2009-02-16T18:18:02+01:002009-02-16T18:18:02+01:00http://friendlybit.com/css/a-couple-of-sites-ive-launched/Emil StenströmLots of opinions here lately, and very few concrete examples of work I've done. I thought I'd take a few minutes of your time and talk about those projects...
<p>Lots of opinions here lately, and very few concrete examples of work I've done. I thought I'd take a few minutes of your time and talk about those projects here.</p>
<p>All of the sites I've built are in <strong>Swedish</strong>. The reason for Swedish is just that they are so much easier to write for. Since English is not my native language, everything takes a little bit longer when having to struggle with vocabulary.</p>
<p>All of the sites are built with <strong>Django</strong>, a framework I've had great success with, which feels both well architectured and easy to get started with (a very unusual combination). Django also lets me write the HTML I want, without getting in the way.</p>
<p>(By the way: there's a <a href="http://groups.google.com/group/django-stockholm">Django User Group</a> forming in Stockholm if you're interested. First meeting this friday)</p>
<h2 id="uttrakadse">Uttråkad.se<a href="#uttrakadse">#</a></h2>
<p>The first one to launch was <a href="http://www.uttr%C3%A5kad.se">Uttråkad.se - hitta saker att göra</a>, a site for everyone that have too much time on their hands. I guess the english version would be "bored.com", which kinda tells you what the site is about, right? :) Anyway, we've played around with having the site very open, with no registration needed at all.</p>
<p>I would say the launch has been a good one, with an <a href="http://www.metro.se/se/article/2008/12/16/19/0353-45/index.xml">article in metro</a> the first week of launch, 153 activities posted, and about 70 daily unique visitors. It has been a fun project to be a part of, and it's been developed together with three friends in a group we call <a href="http://openworks.se">openworks</a>.</p>
<p>Are you bored? Then play around with Uttråkad a bit :)</p>
<h2 id="kundose">Kundo.se<a href="#kundose">#</a></h2>
<p>With our first project barely launched we decided to join an even called 24 hour business camp. The idea was simple: prepare a business idea, and build and launch it in 24 hours. Said and done: 92 entrepreneurs gathered at a luxurious conference center and presented 52 new sites 24 hours later. It was simply the best conference I've been to, and an extreme energy boost to be in a group of doers like that.</p>
<p>Anyway, we launched <a href="http://kundo.se">Kundo - kundtjänst på nätet</a> after 24 hours, a site that companies can use to embed a feedback-widget on their site. Translates to something like "CustomerO.com", it's clearly influenced from <a href="http://getsatisfaction.com/">Getsatisfaction</a> but in Swedish. There's clearly a need for better ways for companies to communicate with their customers in Sweden too.</p>
<p>After the camp we still had some bugs and important features missing, so yesterday me and Björn sat down and squashed all the major ones. So, do you know of a company that needs to take better care of their customers? For free. Send them a link to <a href="http://kundo.se">Kundo</a>. Thanks! :)</p>
<h2 id="samhallsentreprenorse">Samhallsentreprenor.se<a href="#samhallsentreprenorse">#</a></h2>
<p>I've also been busy with Django at work. <a href="http://www.samhallsentreprenor.se/">Samhallsentreprenor.se</a> is a meeting place for people that work in projects that somehow help their local (or global) community. These are people that are incredibly motivated to do good, a group that's of course great to work for.</p>
<p>We've released new versions of the site about every 10 days, so development is fast, and through the development blog people can directly influence future features.</p>
<p>So, do you have ideas for projects that can help people around you? <a href="http://samhallsentreprenor.se/">Sign up on the site and start talking to people</a>.</p>
<h2 id="two-more-projects">Two more projects…<a href="#two-more-projects">#</a></h2>
<p>… are under development and will be announced when they are done. There's no lack of things to do in my world :)</p>
Who are you disappointing with IE6 support?2009-02-13T15:29:37+01:002009-02-13T15:29:37+01:00http://friendlybit.com/browsers/motivation-for-building-for-ie6/Emil StenströmInternet Explorer 6 (IE6) is not getting any younger. With a initial release date of 27:th of August, 2001, it's one of the oldest things touching the...
<p>Internet Explorer 6 (IE6) is not getting any younger. With a initial release date of 27:th of August, <strong>2001</strong>, it's one of the oldest things touching the internet with its slimy fingers. Since then, surfing has taken great leaps forward. In all areas: Web standards, Security, Usability, Rendering speed, Debugging, and more. By working hard to maintain backwards compatibility all of us are missing all of that progress.</p>
<p>Now. You as a web developer have a <strong>responsibility</strong> here.</p>
<h2 id="responsibility-towards-ie6-users">Responsibility towards IE6 users<a href="#responsibility-towards-ie6-users">#</a></h2>
<p>Over the years, IE6 has had <a href="http://secunia.com/advisories/product/11/">142 security issues uncovered</a>. Still 22 of those are not patched. Most IE6 users have no idea of this, but you do. You don't want these people do to their online banking with that kind of browser backing them. You should help these users by educating them, and <strong>making it easy for them to upgrade</strong>!</p>
<h2 id="responsibility-towards-your-employer">Responsibility towards your employer<a href="#responsibility-towards-your-employer">#</a></h2>
<p>If people are paying you do build websites for them it's even worse. By not pushing for upgrade, you're holding their website back. You're downgrading features since "they won't work in IE6", you're over optimizing your javascript because "the site gets slow in IE6", you're hack around CSS issues with extra stylesheets because "IE6 just don't get your styling right". Each hour you work with IE6 backwards compatibility, is one hour less work on new features. Many developers agree that about half their time goes to planning, testing, and patching IE6 issues. That means you could be <strong>twice as productive</strong> to your employer it you did things differently.</p>
<h2 id="responsibility-towards-microsoft">Responsibility towards Microsoft<a href="#responsibility-towards-microsoft">#</a></h2>
<p>Some people will call me and Microsoft-hater because of this article. You're right, I don't like most things Microsoft do. But that doesn't have anything to do with IE6. I'm fine with people upgrading to IE7. In fact, I prefer people upgrading to IE7 over them switching to Firefox. Why? Because IE7 replaces IE6, making it impossible (or too hard for beginners) to switch back to the IE6 junk.</p>
<p>So this has nothing to do with my Microsoft dislike. In fact the Microsoft developers <a href="http://windowshelp.microsoft.com/Windows/en-US/Help/a426bb85-708c-4b75-87e2-874f9be3b4aa1033.mspx">would be delighted</a> if IE6 just stopped working today. Just consider, how much of the code you wrote 8 years ago are you still proud of? I mean, they just released IE8 RC1 for gods sake! Give them a break.</p>
<h2 id="responsibility-towards-yourself">Responsibility towards yourself<a href="#responsibility-towards-yourself">#</a></h2>
<p>By subscribing to friendlybit I assume you care about web standards. You have lengthy arguments with table developers over why their way is outdated, you have already talked about Firefox with your friends, and your parents have switched long time ago. But what looks good when you open your mouth, <strong>you throw away as soon as you start doing real work</strong>. You hack, hack, hack, and patch for IE6. Despite you knowing that this is the wrong way of doing things, despite the pain you feel doing it, despite everything you've read.</p>
<p>What I'm asking of you are two simple things:</p>
<ol>
<li><p>Stop saying: "Well, you need to support IE6 at least, that's what everyone else is doing". Instead think like this: "<strong>Can I find any reasons that warrants disappointing</strong> IE6 users, my employer, Microsoft, and myself". Well, do you? (I'm sure comments will fill up reasons…)</p>
</li>
<li><p><strong>Encourage IE6 users on your website to upgrade</strong>. This is really a no-brainer. If IE6 development is so much of a pain, why don't we do more to stop it? Even if you disagree with everything else I've written, you must agree that promoting upgrade is a good thing. Right? This is the code you need:</p>
</li>
</ol>
<div class="highlight" data-language="HTML"><pre><span></span><span class="cm"><!--[if lte IE 6]></span>
<span class="cm"><div id="upgrade">Your browser is 8 years old! Please upgrade to the latest version by going to</span>
<span class="cm"><a href="http://windows.microsoft.com/en-us/internet-explorer/products/ie/home">Microsoft.com</a></div></span>
<span class="cm"><![endif]--></span>
</pre></div>
<p>And then style the #upgrade div appropriately. It's easy, doesn't rely on javascript, and points users directly do the download page instead of the three intermediary pages on microsoft.com. Add this to your own site, to your employer's sites, to your sisters site. Or maybe buy one of the numerous <a href="http://shop.cafepress.com/internet-explorer">IE t-shirts</a> out there. Hell, print it out and stick it on your dog! <strong>Do something</strong>!</p>
<p>Now. Before you get upset and tell me why your specific case is <strong>so different</strong> from everyone else. Don't. Remember point 1 above. I've just done point 2 above on this site. Now it's your turn!</p>
<p>(Thanks to <a href="http://www.robertnyman.com/2009/02/09/stop-developing-for-internet-explorer-6/">Robert</a> for pushing me to write this)</p>
Google is down2009-01-31T16:47:50+01:002009-01-31T16:47:50+01:00http://friendlybit.com/other/google-is-down/Emil StenströmI'd never this that this day would come, but it actually seems that Google has decided to block all sites in their index. Try searching anything, it will be...
<p>I'd never this that this day would come, but it actually seems that <strong>Google</strong> has decided to block all sites in their index. Try searching anything, it will be marked as spam. I see the same results in the swedish and english version, in Firefox and in Internet Explorer. "This site may harm your computer", clicking that link does not seem to be possible, and I'm guessing it's because it gets millions of hits right now.</p>
<p><strong>Gmail</strong> is also marking emails as spam, they are probably using the same system as Google search. The warning message is: This message may not be from whom it claims to be.</p>
<ul>
<li><a href="http://www.techcrunch.com/2009/01/31/google-flags-whole-internet-as-malware/"><strong>Techcrunch</strong> found out</a> just a couple of minutes after this post.</li>
<li><strong>Twitter</strong> is buzzing with people trying to figure out what's going on.</li>
</ul>
<p><strong>~40 minutes later</strong>: Google is working just fine again, no need for panic. They have even written a <a href="http://googleblog.blogspot.com/2009/01/this-site-may-harm-your-computer-on.html">blog post on the issue</a>, explaining what happened. Seems the URL "/" was mistakenly added as a "bad URL" in the spam filters. Human error obviously.</p>
<p>Heads will be rolling at the Google HQ (or at least someone just got a new nickname).</p>
<img class="alignnone size-full wp-image-415" title="Even google is marked as spam" src="/files/post-media/google_id_down.png" alt="Even google is marked as spam" width="955" height="841">
Downloading MySQL: How bad can it get?2009-01-25T03:31:10+01:002009-01-25T03:31:10+01:00http://friendlybit.com/other/downloading-mysql-how-bad-can-it-get/Emil StenströmMySQL is quite popular on the web these days. Lots of frameworks have support for it, and some frameworks only support MySQL. So lots of people must be...
<p>MySQL is quite popular on the web these days. Lots of frameworks have support for it, and some frameworks <strong>only</strong> support MySQL. So lots of people must be downloading it right? So what do you do when you have a website where most people will be looking for completing one simple task?</p>
<p>Well, you make that task really, and I mean <strong>really</strong>, annoying to complete. No? Yes you do, just look at this:</p>
<ol>
<li><strong>Surf to <a href="http://mysql.com">mysql.com</a></strong>. Note the two horizontal navigation menus, one vertical menu, followed by a seven step banner, and five more columns of links. Note how the top navigaton has the same style as the bottom column headers, and that one is clickable, and the other is not.</li>
<li><strong>Click "Downloads"</strong>, which is the second item, in the second horizontal menu, first tab. Watch how the menu changes to highlight that you're now at the second tab. Watch how the left menu is a list of products, which was the first link in the menu you just clicked, and note that you didn't click products. You're given two choices now, denoted by lots and lots of text, instead of two descriptive headers at the bottom of the page: MySQL Community Server, and MySQL Enterprise.</li>
<li><strong>Decide that you want MySQL Community Server</strong>, ignore the "community downloads"-link that makes you have to choose again, and click the "Download"-button. You're now on the same page as if you would have clicked "community downloads", and now are given information about the product you didn't choose, MySQL Enterprise.</li>
<li><strong>Note in the left menu</strong> that you have somehow chosen version 5.1 of the product, even though you didn't make that choice, and that you get arguments against using MySQL 4.0 if you go to the "Important Platform Support Updates" page. You also get a warning that some enterprise support feature won't work with that version.</li>
<li>Ignore the "NOTE" about MySQL Cluster community edition, the 5.1 changelist, and the suggestion to use MD5 checksums to verify your download. <strong>Now choose your operating system, processor architecture, and packaging option</strong> combinations from a list of 33 options. If you're on windows, and don't know if your processor architecture is denoted "x86" or "x64", you just have to guess now.</li>
<li>You're now take further down the page, showing you both the option you chose and the next option, you didn't chose. If you guessed the last time, now is a chance to change your mind. If you're on windows, <strong>select if you want Windows Essentials, a Zip file/setup.exe combination, or a windows installer</strong>. Find that it isn't Windows installer, but Without installer. Read your options again. Get really confused, since essentials and packaging options doesn't seem to be mutually exclusive.</li>
<li>Guess that you want the first file, and note how that option isn't clickable. Instead, review the version number and MD5 checksum, and <strong>click "Pick a mirror"</strong>. Not because you want to do that, but because there are no other options except a signature link that's smaller.</li>
<li>You're now given the filename of the file you are about to download, and are <strong>asked to register on the site</strong>. The menu shows you're on the DevZone. Since you don't have an account, click "New user", and fill out the seven required fields, including which company you work for. Did you chose Enterprise after all?</li>
<li>At the end of the form, note the link "<strong>No thanks, just take me to the downloads!</strong>" and click it.</li>
<li>Again, you're moved further down the page, to a <strong>list of 150 countries</strong>, denoted by their flag. Read the note that says that this is a list which is sorted by the countries closest to you, and note that it's completely wrong, and ordered alphabetically.</li>
<li>Now <strong>select which protocol</strong> you want to download over, HTTP or FTP. Why on earth would you want to download via FTP from a web browser?! Anyway, select HTTP and you finally get to download the damn file.</li>
</ol>
<p>How can downloading a file be this hard? What did they think? Did they not learn anything from the <a href="http://getfirefox.com/">firefox</a> website? One big green button is all you need, is that too hard for you MySQL devs?</p>
Interface developers and security2009-01-24T00:30:44+01:002009-01-24T00:30:44+01:00http://friendlybit.com/css/interface-developers-and-security/Emil StenströmYou live in a new era, when demanding that people register on your site is no longer enough. There's far too many other sites out that that you're already a...
<p>You live in a <strong>new era</strong>, when demanding that people register on your site is no longer enough. There's far too many other sites out that that you're already a member of, you don't need another one. You need to trust people.</p>
<p>You also want people to contribute to your sites with content somehow. Text is not enough, you want all kinds of "rich" content, and you want people to be able to place them how they want on your page. I mean, we live in a <strong>new era</strong> after all.</p>
<p>Problem is, this <strong>new era thingie talk</strong> makes people forget the basics. Even though this is the future, and we're all bored with "just" hypertext, we can't allow random people to add HTML to our sites. Why? Ask myspace about the <a href="http://namb.la/popular/tech.html">Samy worm</a> from 2005, a little piece of clever front-end code that took their servers flying. What did they do wrong? They tried to let untrusted people embed HTML on their profile pages.</p>
<p>But they even had this clever filter, which cleaned the code first! Well, long story short, using a div with the style attribute set to a background image that points to a javascript url actually execute the javascript in IE6. Didn't think of that did you? So what about the fact that both IE6 and IE7 execute vbscripts in urls prefixed with "vbscript:", just like with javascript. Didn't know that? Ohhh. Perhaps then you shouldn't be trying to let unknown people embed HTML on your site?</p>
<p>Many of these security issues stem from the fact that ordinary well-educated computer scientists <strong>don't know enough about interface development</strong>, HTML, CSS and javascript, and discount them as being something that "anyone" could do. "Even my aunt made this puppy site in like 3 days, how hard can it be?!".</p>
<p>I've always thought that interface development have an undeserved reputation of being easier than "real programming"; something that you can let rookies work with, something that no "real" programmer would ever want. "No, I want to work with hard stuff, not that webby stuff".</p>
<p>If you are in a position where people actually think that, perhaps security could be the way to lift interface development to its proper status. So why not read up on <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross Site Scripting (XSS)</a>, look at examples of vulnerabilities, and pick a couple of examples of <a href="http://www.xssed.com/">big sites that are vulnerable</a>. While you're at it, why not read up on <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">Cross-site request forgery (CSRF)</a> too?</p>
<p>These are real issues that <strong>someone</strong> needs to take into account when building websites. My guess is that the fancy computer scientists will have a very long way to go before grasping this stuff. "Why does IE6 parse 'java script:' as if there where no space in the middle?". You know who's not surprised? Every damn interface developer out there.</p>
<p>So. Go out there, and teach them silly math people how it's done, and what your HTML, CSS and javscript-knowledge is worth. Show them that logic isn't the way we do things around here, that anything can happen when IE6 boots. And… whatever you do… think very hard before letting people embed HTML on your site.</p>
Spotify invite via Twitter or Jaiku2008-12-08T09:00:27+01:002008-12-08T09:00:27+01:00http://friendlybit.com/other/spotify-invite-via-twitter-or-jaiku/Emil StenströmI've talked about Spotify before. It's simply the reason I no longer have any music stored on my computer. You heard it right: No more music stored locally...
<p>I've <a href="/other/spotify-is-a-lot-like/">talked about Spotify</a> before. It's simply the reason I no longer have any music stored on my computer. You heard it right: <strong>No more music stored locally on my computer</strong>.</p>
<p>What Spotify did to convince me to take this step was to really start to <strong>compete with file sharing</strong>. Spotify does just that, but manages to do it in a way that pays artists. This is how:</p>
<ol>
<li><strong>A massive collection of music</strong>: They understood that you need to be able to get everything you ever want. That strange song your mother sang to you when you were five? Although P2P networks might have forgot about it, Spotify has not.</li>
<li><strong>Speed</strong>: If you get a music urge you shouldn't have to wait for it to download. It needs to start right away. In Spotify, you search for the song you want, and click it. The music starts to play instantly. Yep, it should be that easy.</li>
<li><strong>Pays artists</strong>: Everyone downloading copyrighted music from artists that they like, have felt that little sting of "<em>I should really have paid for this</em>". Good artists, that make music I really like, should be paid, it's as easy as that. Spotify does this.</li>
</ol>
<p>So, how do you get ahold of a Spotify account? Well, you get an invite from someone that has one. That one is me, and I have <del>20 invites</del> <del>8 invites</del> <strong>No invites left</strong> to share.</p>
<p><strong>Sorry people, I have no more invites left, thanks for playing!</strong></p>
<blockquote>
<p>If you want an invite, just <strong>post a message on <a href="http://twitter.com">twitter</a> or jaiku</strong>, and say you want one, and <strong>comment here with your e-mail and twitter/jaiku-link.</strong> I will give the first 20 an invite through the mail supplied in the comments. My nick is EmilStenstrom.</p>
</blockquote>
<p>Let the microblogging spotify madness begin!</p>
HTML includes2008-11-29T15:18:49+01:002008-11-29T15:18:49+01:00http://friendlybit.com/html/html-includes/Emil StenströmOne of the first questions beginners ask when starting to learn HTML is how to do includes. They seldom know that includes is what they are asking about,...
<p>One of the first questions beginners ask when starting to learn HTML is <a href="http://www.google.com/search?q=include+html">how to do includes</a>. They seldom know that includes is what they are asking about, but instead feels bad when having to copy and paste that same menu HTML each time they want a new page. "Do I have to type the same thing over and over?".</p>
<p>After asking friends how to solve the problem they get the answer that they now have to learn PHP. Or ASP. Or JSP. Or some other strange language they don't need. And install this thing here, and that thing there. What does your server host support? Oh, no, you need to configure stuff better. No, that setting is insecure… You know the drill, I'm sure you've walked someone through it sometime.</p>
<p>So, a way to include a piece of HTML into a random page would clearly benefit beginners learning HTML. But that's not all:</p>
<ul>
<li><strong>Browsers would be able to cache</strong> components of a page, and therefor load new pages using common components faster.</li>
<li><strong>Less work learning new template languages</strong> just to find that language X does not have a way to include things.</li>
<li>Possible to learn componentization by <strong>looking at existing sites</strong> and learn from them. This is an area we need to be better in.</li>
<li><strong>Easy to make fallbacks</strong> by linking directly to the corresponding HTML snippet.</li>
</ul>
<p>So, how would this be implemented? We need a tag that acts as a kind of include, so what about <code><object></code>? Just point to the HTML file you want and voilá, it gets included. Since this is HTML it would work exactly the same across all server-side languages.</p>
<p>Luckily, this is already in the HTML5 spec. At the <a href="http://www.whatwg.org/specs/web-apps/current-work/#the-object-element">bottom of the object specification</a>. Interestingly, I found it <strong>after</strong> writing this article… Great minds think alike :)</p>
<blockquote>
<p>In this example, an HTML page is embedded in another using the <a href="http://www.whatwg.org/specs/web-apps/current-work/#the-object-element">object</a> element.</p>
</blockquote>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">figure</span><span class="p">></span>
<span class="p"><</span><span class="nt">object</span> <span class="na">data</span><span class="o">=</span><span class="s">"clock.html"</span><span class="p">></</span><span class="nt">object</span><span class="p">></span>
<span class="p"><</span><span class="nt">figcaption</span><span class="p">></span>My HTML Clock<span class="p"></</span><span class="nt">figcaption</span><span class="p">></span>
<span class="p"></</span><span class="nt">figure</span><span class="p">></span>
</pre></div>
<p>Good! And it even seems to work in current browsers (<a href="#comment-31225">Thanks Siegfried</a>). I've tested it in Firefox, Opera, and Safari, and it works the same in all of them. Internet Explorer 6, 7, 8 (beta 2) just ignores it altogether.</p>
<p>The problem is, the current implementation is to handle them just like iframes. And there's of course lots of problems with that approach:</p>
<ul>
<li>Currently, an object element without a height and width gets rendered as a <strong>300 x 150 pixel block</strong>. There is no reason whatsoever to do this when including HTML. This must change for this to be usable.</li>
<li>The included HTML needs to be <strong>stylable</strong> with the CSS rules on the page it's included from. Currently, this does not work, included HTML is treated as an iframe. Must be changed if this is to be usable.</li>
<li>Are HTML components full HTML pages? Do they include a doctype and a <code><head></code>, and do those get included? I assume only HTML <strong>inside <code><body></code> gets included</strong> in the new page. No CSS. No JS linked to in <code><head></code>.</li>
<li>Clicking links inside included HTML should be handled as if the HTML was on the current page. This follows the same concept as if the HTML was included in the server side, and is needed if this is ever going to be used for a menu.</li>
</ul>
<p>So, what do you think, is this a good idea? Personally, I'm hoping more concepts from template languages start to move into HTML.</p>
<blockquote>
<p><strong>Update</strong>: Thanks to the comments (thanks zcorpan) I now have found exactly the above in HTML5. It's called <code><iframe seamless></code>. It meets all the points in my list, and I'm now really looking forward to the first implementation.</p>
</blockquote>
Follow the 10 ground rules, or fail on the web2008-11-20T18:58:16+01:002008-11-20T18:58:16+01:00http://friendlybit.com/tutorial/10-web-ground-rules/Emil StenströmWhen you work with the web, there are a couple of basics you really need to get right. These are things I see people misunderstand over and over again, with...
<p>When you work with the web, there are a couple of basics you really need to get right. These are things I see people misunderstand over and over again, with a varying degree of failiure as a result. Not only individuals make these mistakes, even really big organizations make them, and suffer as a result. So lets get at it.</p>
<h2 id="1-everyone-is-stronganonymousstrong-on-the-w">1. Everyone is <strong>anonymous</strong> on the web, if they want to<a href="#1-everyone-is-stronganonymousstrong-on-the-w">#</a></h2>
<p>If you depend on trying to identify who a particular user on the web is, you will fail in every way possible. This is what lots of law firms try to do, especially in the context of file sharing. You will never ever be able to know who someone online is, if they don't want you to.</p>
<p>Technical reasons: <strong>IP-numbers are easy to fake</strong>, but using proxy servers of different sorts. New services are constantly popping up, that makes this available for unexperienced users. Just push them a little more, send a couple of more <a href="http://en.wikipedia.org/wiki/Cease_and_desist">cease and desist</a> letters and even ordinary home users will start to cloak who they are. It's possible, it's easy.</p>
<p>Social reasons: It's very easy to surf using <strong>someone else's internet connection</strong>. Ways vary from just connecting to an unencrypted wireless network, to just using the free connection at a library or school. And it's getting worse: people are starting to move around while using the web (mobile), hopping from one connection to the next as their geographic position permits. The link between internet connections and users are getting blurrier as we speak.</p>
<p>Despite the above, there are things you can identify and use. One of those is categorizing users into user types. This is what Google (and lots of others) are successfully doing with their advertising system. "Based on what you've showed interest in previously, we think you will like this". This enables you to personalize and customize your content to a particular user type, something that holds lots of economical value (if that's what you're after).</p>
<h2 id="2-give-your-content-away-for-strongfreestrong">2. Give your content away for <strong>free</strong>, or watch someone else do it<a href="#2-give-your-content-away-for-strongfreestrong">#</a></h2>
<p>The web is a gigantic content creation machine, and except for very niched content, you can find anything on it. If you are in the business of selling content online, you will see your profits <strong>steadily decline</strong>. The competition is just too intense when anyone can create content.</p>
<p>How do you tackle that? Well, put your previously costly content online for free, to <strong>drive people to your site</strong>. If the content is good, your will see a massive surge in number of users. Well on the site, you will need to figure out how to <strong>make money of them</strong>, either by showing them ads or getting them to buy something physical.</p>
<p>Industries that depend on online content creation are really living on the edge right now, and for a future prediction, just look at the music industry. You still have some time to rethink your bussiness model.</p>
<h2 id="strong3-linkingstrong-is-the-core-of-the-web"><strong>3. Linking</strong> is the core of the web, make people want to link to you<a href="#strong3-linkingstrong-is-the-core-of-the-web">#</a></h2>
<p>It's called a web because of the links. Trying to limit or control other sites linking to you is fundamentally breaking the web. It's also downright stupid, since every external link is a vote for your site, and a sure way for people to find you. Having an "link policy", controlling how people may link to you, is a sure way to make a fool out of yourself online. Not to say that people won't care one bit about it.</p>
<p>Instead, you should encourage people to link to you. How? By first giving every piece of content a <strong>linkable address</strong>. Many flash- and frame-based sites miss this fact, and instead require users to click through your frontpage to find the content they want. This is a sure way to turn users away. Just make your content linkable, it's not hard.</p>
<p>Then, make sure the content is in such a high quality that users want to link to it. This rules out saying what everyone else is saying, in the same way everyone else is saying it. You need to be <strong>different,</strong> and have <strong>genuinely interesting</strong> content, that no one else has. This is hard, but a problem you need to solve to make it on the web.</p>
<h2 id="4-link-to-strongexternal-sitesstrong-with-go">4. Link to <strong>external sites</strong> with good content, it's all about servicing your users<a href="#4-link-to-strongexternal-sitesstrong-with-go">#</a></h2>
<p>There's billions of sites a user can go to, and you need to work hard to servicing your users if you want their attention. Sometimes your content is so extensive, that no matter how hard you work, users will still want more. This is a perfect situation where you should link to external sites and give your users what they want.</p>
<p>Many newspaper make this mistake, and end up with users leaving their site for Google, trying to find more information about a particular piece of content. They have instead linked to good follow-up content directly, given the user what they wanted, and be accessible via the most used button on the web, the back-button. <strong>Happy users</strong> that have <strong>easy access to your site</strong>, or annoyed users that leave for Google, your choice.</p>
<h2 id="5-people-will-strongcopy-your-contentstrong">5. People will <strong>copy your content</strong>, and there's nothing you can do about it<a href="#5-people-will-strongcopy-your-contentstrong">#</a></h2>
<p>Some people are worried about the copying of their content. And if they see that as an issue, they better be worried. You see, each time someone reads your texts, or looks at your media, it's copied from your server to the users computer. Web browsers are really effective copyright infringement machines, and by just clicking a link, you copy that page.</p>
<p>So if you are worried about users copying your content, please <strong>don't put it online at all</strong>.</p>
<p>Other people think that they can have their content on the web, and still prevent people from copying it. This is pure lunacy, and all ways to prevent copying have failed. People even miss the most obvious way people can copy, by hitting the "Print screen" button on their keyboards. When it comes to video and audio it's a bit more annoying, but everything that comes out of your speakers, or is displayed on the screen, is recordable. So stop worrying about copying, <strong>you can't stop it</strong>.</p>
<p>Instead, know and accept that people will copy your content, and just ask for a simple <strong>link back</strong> if they do. That way, small pieces of your content on other sites will act as marketing for the whole site.</p>
<p>If you want this formalized as a license, there is the <a href="http://creativecommons.org/licenses/by/2.0/">creative commons attribution license</a>, which I use on this site (see footer).</p>
<h2 id="6-use-the-web-to-strongcommunicatestrong-wit">6. Use the web to <strong>communicate</strong> with your users, or watch your impact fade<a href="#6-use-the-web-to-strongcommunicatestrong-wit">#</a></h2>
<p>Almost everything is moving to the web, including most of your business and private life. This of course has implications for web sites. Back in 1999, a couple of smart people sat together and tried to formulate how the future would look for businesses. One of the fundamental truths they found was "<a href="http://www.cluetrain.com/book/markets.html">Markets are conversations</a>". In essence, this means that <strong>you sell stuff by talking</strong> about it with customers. It can be through marketing or through recommendation, but it is talking. When that communication moves to the web, you too better start talking <strong>on the web</strong>. And quickly.</p>
<p>This movement of websites for two-way instead of one-way communication has been given the techy name Web 2.0. And it turns out, this new web is a terribly effective way of communicating. The more people realize this, the more of the conversations will move to the web.</p>
<p>The question is, when hoards of people come to your site to talk to you about your product, are your ready? Or will you give them: "Sorry, this store is closed, but we have this nice brochure you can read…"</p>
<h2 id="7-communicate-with-your-users-in-strongnatural">7. Communicate with your users in <strong>natural language</strong>, marketing speech has no place on the web<a href="#7-communicate-with-your-users-in-strongnatural">#</a></h2>
<p>It's easy to find marketing speech about products today. Companies compete with each other to make sure as much of your field of vision as possible is filled with their message. When people are subjected to that much information they have no interest in, there are consequences. On the early web, the consequences were banner blindness, people simply started ignoring some banner formats. On the modern web, people have started <strong>ignoring marketing language</strong> use instead. The words "Best", "Revolutionize" and "Cheapest", instantly makes people stop reading.</p>
<p>Why? Because companies writing about their own products don't have anything to compare to! They can't say what's <strong>best</strong>, because they don't use their competitor's products. They don't know if the product will <strong>revolutionize</strong> the users life, because they know nothing about the user. And any user can look up how <strong>cheap</strong> they are on a price comparison site.</p>
<p>So what to do? Talk to them like you would to a friend, in the afternoon, <a href="http://www.youtube.com/watch?v=OqhXwjBVVRY">after two beers</a>. This will make sure you don't turn customers away by trying to push to much crap on them. You wouldn't do it to your friend? Then don't do it to potential customers. Just changing your language has huge positive implications, but let me just sum it up like this: <strong>it builds trust</strong>.</p>
<h2 id="8-be-stronghoneststrong-about-what-your-stre">8. Be <strong>honest</strong> about what your strengths are, liars are easily uncovered<a href="#8-be-stronghoneststrong-about-what-your-stre">#</a></h2>
<p>Never has it been so easy to look up facts. Liars are easily uncovered by a couple of soft tappings on a keyboard. What's even better, is that even subjective things can be checked. If someone yells: "Our product is the best one!", you can find out if that's the case in a few seconds. Just read a couple of reviews, look at comparison charts, and you will know.</p>
<p>Lying in person is rather bad, but <strong>lying on the web is worse</strong>. All the facts are so close. A customer is literally seconds away from finding out if you're bullshitting them or telling the truth. This makes it vital not to lie on the web.</p>
<p>If you want to brag anyway, make sure your add a "<strong>we think</strong>" before all your bold claims, and back them up with solid arguments. Because if you say "We've found no cheaper product than our own", and I find out there are others that in fact are, you're not a liar, you're just badly informed.</p>
<h2 id="9-care-about-strongsearch-enginesstrong-and">9. Care about <strong>search engines</strong>, and double your number of users<a href="#9-care-about-strongsearch-enginesstrong-and">#</a></h2>
<p>You are not the only site on the web, and people will spend most of their time on sites other than your own. This means, that if you don't think about how people find your site, all your content work is in vain.</p>
<p>So how are people found? I have yet to see a customer of mine that gets less than 50% of their users from search engines. <strong>Usually 60-70%.</strong> People tend not to understand the implications of this. A e-store could potentially lose over half their sales by misbehaving in Google's eyes. This is huge.</p>
<p>You need to <strong>care about search engines</strong>. Luckily, they are well synced with the ground rules you're reading. If you make your content linkable, unique, interesting, and talk to them in a language they understand, you will be successful. All serious search engine optimization guides will say the same.</p>
<p>The last step, and what many miss, is to <strong>keep track of</strong> how people find you, and what they find. Then feed that information back to your content producers. That way, you can produce content that people actually like.</p>
<p>Or, you could lose half your sales. Your choice.</p>
<h2 id="10-encouraging-and-acting-upon-strongfeedback">10. Encouraging and acting upon <strong>feedback</strong> is currently the best form of marketing<a href="#10-encouraging-and-acting-upon-strongfeedback">#</a></h2>
<p>Asking for feedback is unfortunately still uncommon. Unfortunate because there are so many out there that could benefit from knowing how they can do better. It's also fortunate, because it means that you have a chance to be different, and stand out, just by <strong>asking people what they want</strong>.</p>
<p><a href="http://www.ideastorm.com/">Dell IdeaStorm</a> is a great example of this. They are simply saying: "Hi, we want your feedback", and instantly they have media coverage everywhere. Additionally, they get great feedback on how to improve their business.</p>
<p>Of course, this means you need to act upon feedback too. Telling people that you listen, and then don't is a much worse offense than not listening at all. So find yourself a good chair, hand out the megaphones, and listen carefully.</p>
<h2 id="where-to-now">Where to now?<a href="#where-to-now">#</a></h2>
<p>Thanks for reading this far. This article comes from a frustration over how some companies, and individuals, think the web is still a place were they can makes their own rules. I would therefore like to set the foot down, and tell people what I've learned about the web, about what works and not.</p>
<p>I also know that there are other people out there that needs to read this. Do you know some of them? I then appreciate if you could send them the link. <strong>More people need to read this</strong>.</p>
<p>Thanks.</p>
Templated User Controls in ASP.NET2008-11-18T01:28:43+01:002008-11-18T01:28:43+01:00http://friendlybit.com/other/templated-user-controls-in-aspnet/Emil StenströmGood design repeats itself. It works hard to convey a whole, a feeling of consistency. Once you understand a part of such a design, you know your way around...
<p>Good design repeats itself. It works hard to convey a whole, a feeling of consistency. Once you understand a part of such a design, you know your way around all of it. This is often done by repetition, using the same elements, colors, styles, positioning, and so on. This is a good thing.</p>
<p>Good code <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">never repeats itself</a>. The number of techniques to avoid it are numerous, and all new languages compete in trying to remove as much repetition as possible (Especially the dynamic ones).</p>
<p><strong>Good design repeats itself, good code does not.</strong></p>
<p>With interface development, you <strong>face the conflict</strong> above over and over again. You get a design that (rightly) reuses the same concepts over and over, and you need to implement them in code that makes you write the same logic only once. This same time both when writing the code and later when fixing bugs in it, and deep inside, all programmers know that it's the correct way to do things.</p>
<p>I'm currently working in a .NET project (EPiServer CMS 5), and is faced with a design that uses the same kind of boxes all over the site. The boxes only differ by color and content, so things like shadows and rounded corners are clear repetition that I want to do only once. I'll do the shadows and corners with CSS, but for that I need a couple of wrapper divs. Divs that I only want to specify once, and then reuse.</p>
<p>The prequisites are:</p>
<ol>
<li>I want a <strong>flexible</strong> solution, so I'm not tied to a specific HTML structure (number of divs, or even if I use the div tag or not).</li>
<li><strong>No HTML in properties</strong> that get sent to user-controls</li>
<li><strong>No HTML in code-behind</strong> (a common way in .NET to split logic (code-behind) and templates (ASP.NET and HTML))</li>
</ol>
<p>What I came up with was <a href="http://msdn.microsoft.com/en-us/library/36574bf6.aspx">templated user controls</a>. They provide a way to write controls that wrap any other controls you may have, and add content around them. And it's easy to write and user. This is how the one I wrote is used:</p>
<div class="highlight" data-language="ASPX-CS"><pre><span></span><span class="nt"><MyProject:Box</span><span class="w"> </span><span class="na">runat=</span><span class="s">"server"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><Contents></span>
<span class="w"> </span><span class="nt"><h2></span>Random<span class="w"> </span>header...<span class="nt"></h2></span>
<span class="w"> </span><span class="nt"><asp:Repeater</span><span class="w"> </span><span class="na">runat=</span><span class="s">"server"</span><span class="nt">></span>...<span class="nt"></asp:Repeater></span>
<span class="w"> </span>...
<span class="w"> </span><span class="nt"></Contents></span>
<span class="nt"></MyProject:Box></span>
</pre></div>
<p>It simply wraps anything inside it (in this case a heading tag and a asp repeater), and lets me do whatever I want with them. In my case, I wanted to add some generic HTML around lots of different content, but you could do anything you wanted.</p>
<p>This is how the above was implemented. First the code-behind:</p>
<div class="highlight" data-language="CSHARP"><pre><span></span><span class="k">using</span><span class="w"> </span><span class="nn">System.Web.UI</span><span class="p">;</span>
<span class="k">namespace</span><span class="w"> </span><span class="nn">MyProject.templates.units</span>
<span class="p">{</span>
<span class="w"> </span><span class="na">[ParseChildren(true)]</span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="k">partial</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Box</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="n">Web</span><span class="p">.</span><span class="n">UI</span><span class="p">.</span><span class="n">UserControl</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="n">ITemplate</span><span class="w"> </span><span class="n">contents</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">null</span><span class="p">;</span>
<span class="w"> </span><span class="na">[TemplateContainer(typeof(TemplateControl))]</span>
<span class="w"> </span><span class="na">[PersistenceMode(PersistenceMode.InnerProperty)]</span>
<span class="w"> </span><span class="na">[TemplateInstance(TemplateInstance.Single)]</span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ITemplate</span><span class="w"> </span><span class="n">Contents</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">get</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">contents</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">set</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">contents</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">value</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Page_Init</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">contents</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="k">null</span><span class="p">)</span>
<span class="w"> </span><span class="n">contents</span><span class="p">.</span><span class="n">InstantiateIn</span><span class="p">(</span><span class="n">PlaceHolder1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>… and then the "code-front":</p>
<div class="highlight" data-language="ASPX-CS"><pre><span></span><span class="nt"><%@</span><span class="w"> </span><span class="n">Control</span><span class="w"> </span><span class="n">Language</span><span class="o">=</span><span class="s">"C#"</span><span class="w"> </span><span class="n">AutoEventWireup</span><span class="o">=</span><span class="s">"true"</span><span class="w"> </span><span class="n">CodeBehind</span><span class="o">=</span><span class="s">"Box.ascx.cs"</span><span class="w"> </span><span class="n">Inherits</span><span class="o">=</span><span class="s">"MyProject.templates.units.Box"</span><span class="w"> </span><span class="nt">%></span>
<span class="nt"><div</span><span class="w"> </span><span class="na">class=</span><span class="s">"box"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><div</span><span class="w"> </span><span class="na">class=</span><span class="s">"boxwrapper"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><asp:Placeholder</span><span class="w"> </span><span class="na">runat=</span><span class="s">"server"</span><span class="w"> </span><span class="na">ID=</span><span class="s">"PlaceHolder1"</span><span class="w"> </span><span class="nt">/></span>
<span class="w"> </span><span class="nt"></div></span>
<span class="nt"></div></span>
</pre></div>
<p>I think this is a <strong>really useful</strong> way to write user controls, especially for those of you that work as interface developers in a .NET world. Asking the people around me I found that quite a few didn't know how templated user controls worked, so I hope I will be of use to some of you out there. Happy coding!</p>
Install MySQL-python on Mac OS X (leopard)2008-10-31T18:37:18+01:002008-10-31T18:37:18+01:00http://friendlybit.com/tutorial/install-mysql-python-on-mac-os-x-leopard/Emil StenströmWhat a pain. Getting mysql to work with python is the single most annoying step in getting Django up and running (if you choose MySQL as the database). You...
<p>What a pain. Getting mysql to work with python is the single most annoying step in getting Django up and running (if you choose MySQL as the database). You see, python requires drivers to be able to talk to MySQL, and you have to compile those yourself. I just devoted several hours last night to help friends do what I did some months ago. This time, I thought I document it right here.</p>
<h2 id="how-to-install-mysql-python-on-mac-os-x">How to install MySQL-python on Mac OS X<a href="#how-to-install-mysql-python-on-mac-os-x">#</a></h2>
<p><strong>Step 1</strong>: <strong>Brace yourself</strong>, this proccess is really really annoying.</p>
<p><strong>Step 2</strong>: <a href="http://dev.mysql.com/downloads/mysql/5.0.html#macosx-dmg"><strong>Download MySQL</strong> for Mac</a> (Skip registration by clicking the link below the login form). You probably want "<a href="http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-5.0.67-osx10.5-x86.dmg/from/http://mysql.mirror.kangaroot.net/">Mac OS X 10.5 (x86)</a>". Is it possible to use some other version of MySQL? Yes, as long as you have a version that includes the source code (<a href="http://www.mamp.info/en/mamp.html">MAMP</a> does not include them, so it won't work). You'll need the source later on.</p>
<p><strong>Step 3</strong>: <strong>Install MySQL</strong> by mounting the image you just downloaded, and double-clicking the package file for MySQL. Also install the prefPane that's included in the package. That adds an icon the system admin that lets you start and stop MySQL, very convenient.</p>
<p><strong>Step 4</strong>: <strong>Make the mysql command accessible from anywhere</strong> by adding it to your PATH (a variable that holds all directories the terminal looks in to find the command you're trying to execute). The below just adds mysql's bin directory (it's probably the one I'm using below) to the PATH you currently are using:</p>
<div class="highlight" data-language="BASH"><pre><span></span><span class="nb">export</span><span class="w"> </span><span class="nv">PATH</span><span class="o">=</span>/usr/local/mysql/bin:<span class="nv">$PATH</span>
</pre></div>
<p>You probably want to add this line to a file called <strong>.bash_profile</strong> (yes, it starts with a dot), that is situated in your home directory (which you get to by just typing "cd"). This file gets run each time you start a new terminal, so it makes sure the mysql command is always accessible, no matter where you are.</p>
<p><strong>Step 5</strong>: <strong><a href="https://sourceforge.net/project/showfiles.php?group_id=22307&package_id=15775">Download MySQL-python</a></strong>, you probably want the file that ends with .<strong>tar.gz</strong>.</p>
<p><strong>Step 6</strong>: <strong>Unpack the file</strong> you just downloaded in an empty directory (anywhere)</p>
<p><strong>Step 7</strong>: <strong><a href="http://developer.apple.com/technology/xcode.html">Download XCode</a></strong> from Apple. The reason you need this is because XCode includes a C++ compiler you will use when installing MySQL-python soon. The download is huge (1 Gb), and to be able to download you first need to fill in a long form. The registration process for Apple Developer Connection is about the worst things Apple has ever created, so after completing it, you will either laugh or be really annoyed, just pick and choose. You do need XCode however.</p>
<p><strong>Step 8</strong>: <strong>Install the XCode Tools</strong> <strong>package</strong> by first mounting the file you just downloaded, and then double-clicking on the <strong>XCode Tools</strong> package. It's the only one you need from the huge set of junk you just downloaded.</p>
<p><strong>Step 9</strong>: Try installing MySQL-python by going to the directory where you unpacked it and typing:</p>
<div class="highlight" data-language="BASH"><pre><span></span>python<span class="w"> </span>setup.py<span class="w"> </span>install
</pre></div>
<p>This will attempt to install the drivers, but <strong>will fail</strong>. This is because the coders behind MySQL-python have failed to fix a very simple bug in types.h (<a href="https://sourceforge.net/tracker/?func=detail&aid=1808476&group_id=22307&atid=374932">1808476</a> - "#define of uint breaks compiling on Mac OS X 10.5"). However, you can easily fix it yourself: Look for a reference to types.h in the terminal. When you find it, open that file in your favorite text editor and comment out line 92, which should say something about <code>#define</code> and <code>uint</code> (comments in C++ are double forward slashes: //).</p>
<p><strong>Step 10</strong>: Now, <strong>try the above command again</strong>. It should install fine. If it doesn't, you will probably find out why by looking in the terminal for errors while compiling.</p>
<p>What did I say, isn't this process about 7 steps to long? Well, I hope this little guide helps someone.</p>
OpenID, Nofollow removed, Comment counts, and IE7 fixes2008-10-19T15:48:03+02:002008-10-19T15:48:03+02:00http://friendlybit.com/css/openid-nofollow-removed-comment-counts-and-ie7-fixes/Emil StenströmI'm added a few features to the site: OpenID support: Instead of typing your name and e-mail you could instead sign in with an OpenID-enabled URL. Or you...
<p>I'm added a few features to the site:</p>
<p><strong>OpenID support</strong>: Instead of typing your name and e-mail you could instead sign in with an OpenID-enabled URL. Or you could completely ignore it, and go on as usual.</p>
<p><strong>Nofollow restriction removed</strong>: WordPress by default adds rel="nofollow" to all links that people write in comments. It's a good way to decrease the impact of spam. Thing is, I strictly moderate comments, and have three plugins that prevent spam (Akismet, Spam Karma 2, and Bad Behavior). Since spam really isn't a problem, I've decided to remove the nofollow from your links, if you've posted more than three comments.</p>
<p><strong>Comment counts</strong>: To make it easier to see who you can trust and not in the comments I've added a comment count next to the name. Damn, I've commented a lot :)</p>
<p><strong>IE7 fixes</strong>: There were script errors in IE7 since I'm trying to do funky stuff with opacity on the search field. I've fixed that. Also, the number of subscribers wasn't visible in IE7. They are now.</p>
<p>Over and out.</p>
IE7 hover bug: z-index ignored (and other properties)2008-10-12T20:17:04+02:002008-10-12T20:17:04+02:00http://friendlybit.com/css/ie7-hover-bug-z-index-ignored-and-other-properties/Emil StenströmI'm implementing a rather different design right now for an intranet, and have found a bug I thought you'd like to know about. If you restyle things with...
<p>I'm implementing a rather different design right now for an intranet, and have found a bug I thought you'd like to know about. If you restyle things with :hover, you might have to add an extra property for the rule to be applied in IE7.</p>
<p>How is this design different? Well, it built on columns that are overlapping each other. When you hover one of the columns, that column get placed on top (temporarily). You think you need javascript for this? You don't (if you can live with not supporting IE6).</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">menu</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">content</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">sidebar</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">z-index</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">menu</span><span class="p">:</span><span class="nd">hover</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">content</span><span class="p">:</span><span class="nd">hover</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">sidebar</span><span class="p">:</span><span class="nd">hover</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">z-index</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Simple isn't it? Now you just have to absolutely position the three columns. By the way, working with absolute positioning is ok as long as you don't need a cleared footer below the three columns. Strange that not more people use this.</p>
<p>Anyway, the above doesn't work in IE7. It should, because IE7 supports :hover on all elements, including my "div columns". Some googling led me to an old IE6 bug where some elements are ignored on links. The bug talks about IE6 and the color property being ignored, but the same seems to apply to IE7 and z-index.</p>
<p>So, long story short, just add <code>display: block</code> to the hover rule and everything works fine. As the link above dictates, many different rules work, the important thing is that it must be a new rule, which you <strong>haven't used before</strong> on that element. But you don't set display: block; on divs, do you? So it should work fine.</p>
<p>Hope it helps some frustrated soul out there :) And long live funky designs.</p>
Yellow fade with CSS and a simple image2008-10-04T20:19:09+02:002008-10-04T20:19:09+02:00http://friendlybit.com/css/yellow-fade-with-css-and-a-simple-image/Emil StenströmVia Think Vitamin I find a cool way to highlight the current element. Lots of people do this by calling some kind of javascript library, it's so common it's...
<p>Via <a href="http://www.thinkvitamin.com/features/css/stay-on-target">Think Vitamin</a> I find a cool way to highlight the current element. Lots of people do this by calling some kind of javascript library, it's so common it's been dubbed the <a href="http://www.37signals.com/svn/archives/000558.php">yellow fade technique</a>. But javascript isn't really needed, you just need CSS and an image.</p>
<p id="example">
First: you can jump to any id on the current page by appending #some-id-here to the url. This includes all the "semantic" ids you've added to the page such as #content, #sidebar, and so on. Very useful if you want to point out a certain section of a page to a friend, just look at the source, try to find an id nearby, and add it to the url.
</p>
<p>If you want to make things even easier on your own site, you can visually highlight things that get referenced via the above method. That's where the :target psuedo selector jumps in to save your day. Please note that :target is CSS3, and only currently works in <a href="http://reference.sitepoint.com/css/pseudoclass-target">non-crap browsers</a>. But perhaps this effect is something not all users really need?</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">a</span><span class="p">:</span><span class="nd">target</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#234af5</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>This highlights all links that get referenced via the URL with a nice blue color. So they need an id added. Makes perfect sense for all kinds of documentation where you want to refer someone to a certain method or even sentence.</p>
<p>But it gets better:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">:</span><span class="nd">target</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="s2">"/images/yellow-fade.gif"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>We've removed the limit of only targeting links with by using :target straight off. So all targeted elements will get affected by this rule. What next? Well, we use a small animated image to fade from one color to the next. It's a really easy way to add dynamics to a page.</p>
<p>Try the effect by <a href="#example">jumping to the code example</a> above.</p>
<p>I really think this makes internal links a whole lot more useful, especially for jumping to the bottom of the page, where it's not possible for the browser to scroll down enough to get the targeted element to the top. Needless to say, I've added this effect to this site too. Hope you can find something to use it for too.</p>
Django – the fun framework (presentation)2008-09-26T17:07:14+02:002008-09-26T17:07:14+02:00http://friendlybit.com/other/django-the-fun-framework-presentation/Emil StenströmYesterday I attended the excellent Geek Meet hosted by Robert Nyman at the Creuna office. I held a presentation about the Django web framework, and took...
<p>Yesterday I attended the excellent <a href="http://robertnyman.com/geekmeet/">Geek Meet</a> hosted by Robert Nyman at the Creuna office. I held a presentation about the Django web framework, and took some time today to add some comments in english and make a PDF-file of the presentation. Would you like to know why Django is more fun than what you're using right now?</p>
<p>So go ahead and have a look at the presentation: <strong><a href="/files/Django%20-%20the%20fun%20framework.pdf" data-no-instant>Django - the fun framework</a></strong> (11 Mb, PDF with english comments)</p>
Ten commandments of update services2008-09-21T23:10:25+02:002008-09-21T23:10:25+02:00http://friendlybit.com/other/ten-commandments-of-update-services/Emil StenströmI'm getting increasingly annoyed with update services shipped with popular applications. It's looks like it's getting worse and worse, and I think someone...
<p>I'm getting increasingly annoyed with update services shipped with popular applications. It's looks like it's getting worse and worse, and I think someone should stand up and say <strong>enough is enough</strong>.</p>
<ul>
<li><a href="#adobe">Adobe Update</a></li>
<li><a href="#google">Google Update</a></li>
<li><a href="#microsoft">Microsoft Update</a></li>
<li><a href="#ten">Ten Commandments of Update Services</a></li>
</ul>
<p>Let me start by showing when updates go wrong:</p>
<h2 id="adobe">Adobe Update<a href="#adobe">#</a></h2>
<p><img class="secondary" src="/files/post-media/adobe_logo.jpg" alt="" />I start Adobe Fireworks because I want to resize an image I have. After it has started and the image has loaded the update service prompts me that there are new updates available. For what? It doesn't say, so I click more info and get a list of things. Strange: <strong>None of them seem related to Fireworks</strong>.</p>
<p>The update starts, and tells me I <strong>have to close Fireworks</strong> to complete it. Bah, I just started it! I'm trying to resize an image here, remember? But Ok, this time. Next it tells me to close Firefox. What?! All my precious tabs I've saved for later reading! Bitches.</p>
<p>The download begins, and the <strong>progress window takes focus</strong> over the other stuff I'm doing while not looking at the progress bar. *Repeated clicking to hide the window*. Then when it's done it takes focus again, and asks me to click the only button available. GAH?!</p>
<p>Ok, done. Why was I starting Fireworks again? And hey, what's those <strong>new PDF icons</strong> doing in my Links toolbar in Internet Explorer?</p>
<h2 id="google">Google Update<a href="#google">#</a></h2>
<p><img class="secondary" src="/files/post-media/google-logo.jpg" alt="" />Oh, a new web browser: Google Chrome, I surely want to try it out. *Couple of hours of fiddling*. Nah, I still like Firefox more, I'll go back to using that one. <strong>Wait, what's that GoogleUpdate.exe process doing there</strong>? I'll try closing Chrome. Nope, still there. Ok, I'll force it to close. Hmm, it restarts after a while. Ok, must be some kind of process that starts with Windows. Ah, registry setting, lets remove that one. *Reboot*. Still there?! Ah, they also installed it as a service. Lets remove that too. Finally!</p>
<p>What's that? A new version of Google Gears! *Installing*. Hmm… What's that GoogleUpdate.exe process doing there? GAH! What were you thinking Google?!</p>
<h2 id="microsoft">Microsoft update<a href="#microsoft">#</a></h2>
<p><img class="secondary" src="/files/post-media/logo_microsoft_small.gif" alt="" />I really should make sure my OS is up to date. Lets go to the windowsupdate website. What? I need to run IE5 or later? Ah, no Firefox support, damn it. Lets switch browser. Ok. Install validation thingie? Ehm… I guess I have no choice. *Waiting*. Ok, now let's see if there's some updates, Express or Custom? Custom, of course. *Waiting quite a long time*. Why are you making me look at a progress bar? Ok, no OS upgrades, but there's some update to Windows Media player. Yeye, I guess it couldn't do any harm (not that I use that one). Trust ActiveX thingie? Yeye, I know what I'm doing. *Waiting some more, with focus stealing*. "Please restart your computer to complete the installation". Sigh.</p>
<p>So why don't I just use Windows Update program instead? Well, there's a window that pops up every 5 minutes that remind you that you have to restart the computer. Do you know how annoying that one is? No, it's MORE annoying than that.</p>
<h2 id="ten">Ten Commandments of Update Services<a href="#ten">#</a></h2>
<p>So I hope that's enough evidence that big companies have no idea how do conduct a decent update of their own program. So let me offer some (free of charge) advise:</p>
<ol>
<li>If your update is web based, <strong>let me use any modern browser I want</strong>. Don't start by getting me annoyed.</li>
<li>Check for updates <strong>right before the program starts</strong>. I know that you want me to close the app while it's being updated, but why on earth do you let me start it then? Lets keep it simple, update before the program starts, and resume starting the app when you're done.</li>
<li><strong>Don't leave processes running in the background</strong> when I close the program. When I close your program, I don't care about you, or any updates to your program.</li>
<li><strong>Only update the current program</strong>, not bundled ones. I know you want me to have the latest versions of all your programs, but odds are I don't even use them. Update those programs when I start them, not now.</li>
<li><strong>Show me what gets updated</strong>, and if possible link to a change log. If you want me to download 70 Mb you need to first talk me into why I need it. You may want to hide detailed info for inexperienced users, but could you please then remember that I'm not one of those?</li>
<li>If it's a tiny update (less than 1 Mb), you can just <strong>go ahead and install right away</strong>. You don't even have to prompt me.</li>
<li><strong>Download and install in the background</strong>, without stealing my focus. If you're shipping a big pile of fixes (ie. the version I bought was not done), you have to let me do other stuff while you update. Like surfing the web. It's not Ok it require that I close unrelated programs, sorry.</li>
<li><strong>Never ever touch my browser bookmarks</strong>. Never add things to the quicklaunch bar. Never make things start automatically unless I've told you that's what I want (why do most people have a Quicktime icon in their systray?). The only way of getting into my bookmarks or my quicklaunch bar is writing a really good application. You can't force me to like you. The opposite works well though.</li>
<li><strong>Never require me to restart the computer</strong>. There's only one exception for when you may: when I'm updating the operating system. No excuses.</li>
<li><strong>When you're done</strong>, just start the program. I don't want to confirm anything, I want to get to work using your app.</li>
</ol>
<p>(Bonus point from <a href="#comment-31047">James Socol</a> in the comments: 11. <strong>Use incremental downloads</strong>, so I don't have to download stuff I already have installed.)</p>
<p>If you are a software company, and can't manage the above, just do it the old fashion way: let me manually download a file from your website. That will annoy me much less than a bad automatic process. Or if you want things to be really convenient: <strong>write a web application instead</strong>.</p>
<p>Now get to work. I've had it.</p>
The Open Web: Can it deliver?2008-09-01T22:58:08+02:002008-09-01T22:58:08+02:00http://friendlybit.com/css/the-open-web-can-it-deliver/Emil StenströmIt's ringing through my head as Microsoft releases Silverlight, as Adobe forces another version of Flash or Air, and as Sun tries to push JavaFX into the...
<p>It's ringing through my head as Microsoft releases Silverlight, as Adobe forces another version of Flash or Air, and as Sun tries to push JavaFX into the spotlight. It's a dark whisper when I read how many still use old browsers (hello IE6!), or when I see Javascript being used poorly by otherwise knowledgeable programmers. It's getting obvious when people complain over how hard and hacky HTML and CSS is.</p>
<p>People are simply not getting their job done fast enough. Just because we've hacked and hacked to the point of getting used to it, doesn't mean our way of writing web apps is the best way. In the end it about delivering to end users or paying clients, and they care more about <strong>what</strong> you deliver than <strong>how</strong>. I'm not saying we are working slower than before, it's the opposite, new tools makes web development less annoying. But I am saying that we get less work done in relation to the expectations.</p>
<p>So what do they expect? Well, they want flashy effects. The want application behavior. They want snappy response times, bright colors, and "Wow!"-reactions. For our clients, the web is getting more crowded every day and they need to fight harder and harder for people's attention. That means you need to fight harder on their behalf.</p>
<p>Say you are a pro open standards developer, like me. What tools do you have to grab people's attention? Valid HTML? DIVs with fading color? AJAX? No way man. A good Flash developer can get a wow reaction by the time you've chosen doctype (or at least by the time you've booted IE6).</p>
<p>So you turn to Google, and look for the latest and hottest in standards development. And you find that you need to use Javascript and Flash (sIFR) to render custom fonts. You find that you need to use (Adobe) Photoshop to add highlights and shadows on your headers. You find that you have to hack severely to be able to use alpha transparent images. To do any kind of animation, you need a big Javascript library, because browser makers have not yet (yes, it's 2008) been able to collaborate on how the language should work.</p>
<p>You say that standards have to take time. That everyone needs to come together and thoroughly discuss important issues. The right committees and councils needs to be formed. Meanwhile Microsoft prepares for the release of Silverlight 2.</p>
<p><strong>Have you no sense of urgency?</strong></p>
7 silliest W3C specs ever published2008-08-13T22:20:52+02:002008-08-13T22:20:52+02:00http://friendlybit.com/other/7-silliest-w3c-specs-ever-published/Emil StenströmW3C is producing lots and lots of good specifications and we seriously have their joined effort to thank for a lot of today's web. But everything released...
<p>W3C is producing lots and lots of good specifications and we seriously have their joined effort to thank for a lot of today's web. But everything released by them isn't all nice. I've digged deep into obscure search results to find, that's right, the <strong>silliest specifications ever</strong>. *Drumroll*.</p>
<p><a href="http://www.w3.org/TR/NOTE-HTMLplusTIME">HTML+TIME</a>: Why not add timers to HTML? Didn't you always want to only display that div only the first 4 seconds after load. Could this be combined with the blink tag somehow?</p>
<p><a href="http://www.w3.org/TR/WD-wwwicn.html">Predefined icon entities</a>: No more images needed! Instead, let browsers implement whatever icons they want and just use them by typing &calculator;, &fax; or &www;. I love the example icon for &gopher;, is that an orc?</p>
<p><a href="http://www.w3.org/TR/curie/">CURIE Syntax</a>: There are also huge specifications for nothing. What about a 2000+ word specifcation for the syntax: "charcters:characters"? This is what happens when you put too many "scientists" in one room.</p>
<p><a href="http://www.w3.org/TR/1999/WD-Micropayment-Markup-19990825/">Micropayments in HTML</a>: If you're going to make micropayments on the web, first build your payment system, then add lots of attributes you don't need. Then make sure you pick a short code for your payment system, and get that one in the spec. Ehmm. No.</p>
<p><a href="http://www.w3.org/TR/WD-jepi-uppflow-970106">Selecting Payment Over HTTP</a>: If you are into paying, but don't really like interfaces, this one is for you. You can't pay through it though, just select how to pay. Makes sense, doesn't it?</p>
<p><a href="http://www.w3.org/TR/2008/WD-css3-marquee-20080801/">CSS Marquee Module Level 3</a>: Remember the <code>marquee</code> element? What if you could implement that on any element, using only CSS3? Isn't marquee behavior? I guess not. "The deadline for comments is 1 September 2008".</p>
<p><a href="http://www.w3.org/TR/2008/WD-wai-age-literature-20080514/">Accessibility for old people</a>: Very strange. This isn't a specification but a literature review. Could this be the first step for W3C to go into book recommendations? I love the chapter of how to define an old person.</p>
<p>That's all I can find. Now I leave it open to you to fill in with the comments about how useful they could be, and how SOAP should be in the list. Over to you, dear audience.</p>
Google Reader subscriptions on a WordPress Page2008-08-09T17:09:43+02:002008-08-09T17:09:43+02:00http://friendlybit.com/other/google-reader-subscriptions-on-a-wordpress-page/Emil StenströmInstead of posting new lists of blogs I follow over and over again I thought I'd make a permanent place for them. So I just exported all of the blogs I...
<p>Instead of posting new lists of blogs I follow over and over again I thought I'd make a permanent place for them. So I just <strong>exported all of the blogs I follow</strong> from Google Reader (Settings -> Import/Export) and <strong>imported them to WordPress</strong> (Write -> Links -> Import Links (in the sidebar)). <a href="http://en.wikipedia.org/wiki/OPML">OPML</a> is a great format!</p>
<p>Then I created a <a href="http://codex.wordpress.org/Pages#Page_Templates">WordPress Page template</a> that simply printed the content of that page <strong>followed by all my imported links</strong>. This following is the code needed (as a file called links.php in your template directory):</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="cp"><?php</span>
<span class="c1">// Template Name: Links</span>
<span class="cp">?></span>
<span class="cp"><?php</span> <span class="nx">get_header</span><span class="p">();</span> <span class="cp">?></span>
<span class="x"><div id="content"></span>
<span class="x"> </span><span class="cp"><?php</span> <span class="k">while</span> <span class="p">(</span><span class="nx">have_posts</span><span class="p">())</span> <span class="o">:</span> <span class="nx">the_post</span><span class="p">();</span> <span class="cp">?></span>
<span class="x"> <div class="post" id="post-</span><span class="cp"><?php</span> <span class="nx">the_ID</span><span class="p">();</span> <span class="cp">?></span><span class="x">"></span>
<span class="x"> <h1></span><span class="cp"><?php</span> <span class="nx">the_title</span><span class="p">();</span> <span class="cp">?></span><span class="x"></h1></span>
<span class="x"> <div class="entry"></span>
<span class="x"> </span><span class="cp"><?php</span> <span class="nx">the_content</span><span class="p">();</span> <span class="cp">?></span>
<span class="x"> </span><span class="cp"><?php</span> <span class="nx">wp_list_bookmarks</span><span class="p">();</span> <span class="cp">?></span>
<span class="x"> </div></span>
<span class="x"> </div></span>
<span class="x"> </span><span class="cp"><?php</span> <span class="k">endwhile</span><span class="p">;</span> <span class="cp">?></span>
<span class="x"></div></span>
<span class="cp"><?php</span> <span class="nx">get_sidebar</span><span class="p">();</span> <span class="cp">?></span>
<span class="cp"><?php</span> <span class="nx">get_footer</span><span class="p">();</span> <span class="cp">?></span>
</pre></div>
<p>Now just create a new page, and select the Page Template "Links" at the bottom. Fill out a page title and an introduction text and press Save. Voilá!</p>
<p>The final touches was adding two new categories, "Blogs I follow" in English and Swedish, moving all links to one of those, and removing everything not related to web development or media. Some bastards also both have great blogs and are my friends, so I removed some duplicates too.</p>
Why adding variables to CSS is a good thing2008-08-07T16:29:24+02:002008-08-07T16:29:24+02:00http://friendlybit.com/css/why-adding-variables-to-css-is-a-good-thing/Emil StenströmVia Simon Willison I find that Bert Bos, one of the creators of CSS, has written an article on why variables shouldn't be included in CSS3. I thought I'd...
<p>Via Simon Willison I find that Bert Bos, one of the creators of CSS, has written an article on why <a href="http://www.w3.org/People/Bos/CSS-variables">variables shouldn't be included in CSS3</a>. I thought I'd try to explain why I think <strong>they should</strong>.</p>
<h2 id="professional-perspective">Professional perspective<a href="#professional-perspective">#</a></h2>
<p>Bert posts statistics of stylesheet usage from the W3C site, and means that most stylesheets are very small, and on those, variables are not really needed. I agree. You can get away with simple search-replace in those simple cases. But Bert also finds that there are bigger sheets: "largest hand-written style sheet: 1462 lines (bought from a Web design company)". I work at one of those companies, and almost all CSS files I write exceed 1000 lines.</p>
<p>In those cases, I think CSS variables would help me a lot. Especially for margins. Matching several margins together by copying the same value over and over again isn't maintainable. Search replace on a pixel value is a sure way to mess up your whole stylesheet: who says you only use 5px for those margins? So <strong>there is</strong> a use case for some kind of variables.</p>
<h2 id="so-we-need-variables-but-how">So we need variables, but how?<a href="#so-we-need-variables-but-how">#</a></h2>
<p>Bert then suggests that those people should use a solution such as <a href="http://interfacelab.com/variables-in-css-via-php/">PHP to generate CSS</a>. So we should invent a new language for generating CSS with PHP? And another language for generating CSS from Ruby, from Java, from .NET, and so on. Why shouldn't we go this way? It's the path HTML has taken. And this is a hard nut to crack. How is CSS different from HTML? Why should CSS have variables when HTML doesn't?</p>
<p>I think the answer is that we should add variables to both languages. They are very similar in nature, so they should be treated the same. Because what has changed since when CSS was created is that we've started building bigger and more complex sites. And if CSS starts to be too cumbersome to use, people will start looking elsewhere, to Flash, Air, Silverlight and so on. CSS needs to adapt to the more complex sites people are building today.</p>
<p><strong>I'd rather see CSS follow the times and add variables, than seeing frustrated professionals move to proprietary technologies</strong>.</p>
<h2 id="so-what-about-beginners">So what about beginners?<a href="#so-what-about-beginners">#</a></h2>
<p>Bert's article deals a lot with beginners, and how it will be harder for them to understand another level of abstraction. Lets make it clear at first that CSS already is too hard for beginners. To make a very simple layout you need to understand floats (yes, almost everyone needs columns), and floating is really confusing (ever tried to explain float/clear to someone?). Even for someone like me, who has worked with CSS for years, floats still puzzle me regularly.</p>
<p>People will give up on CSS when they encounter floats (yes, I've seen this), not when they find CSS variables. They can just choose not to use variables, while they really need to know floats. Also, CSS variables are easier to understand than cascading values. I mean really, if I set font-size on body, why do my links get larger? That's a very similar concept that is central to CSS.</p>
<h2 id="summary">Summary<a href="#summary">#</a></h2>
<p>CSS Variables make it easier for professionals to do their job. It doesn't require inventing new template languages. It doesn't make the language overall harder either. The people that can handle floats and cascading, can handle variables too. <strong>We need variables</strong>.</p>
Don’t waste time writing HTML and CSS2008-07-10T00:02:50+02:002008-07-10T00:02:50+02:00http://friendlybit.com/css/dont-waste-time-writing-html-and-css/Emil StenströmWhen you've worked with front-end development for a while, you start thinking about effectiveness. So without further ado, here's my four best ways to be a...
<p>When you've worked with front-end development for a while, you start thinking about effectiveness. So without further ado, here's my four best ways to be a more effective front-end developer. Feel free to add more ideas as comments!</p>
<h2 id="1-do-you-need-html-or-css-for-this">1. Do you need HTML or CSS for this?<a href="#1-do-you-need-html-or-css-for-this">#</a></h2>
<p>Lots of times when I get stranded on hard problem and sit back, I realize that I really <strong>shouldn't be trying to use CSS to solve all layout problems</strong>. Assuming a rounded corner box will have to scale in all directions (up to 8 images!), when it really is fixed width and height (1 image), is an indescribable waste of everyone's time. Look closely at the design you're trying to implement: does it really have to be as flexible and scalable as you think? Shifting to that mindset saves me hours of work per day.</p>
<p>One thing that many developers forget is that not all designers care for exact pixels. If something is really hard to develop, walk over to their table and suggest a change. You'll soon start to notice that designers are real people too, and that they have as much flexibility as you do. It's just as easy to call them up, so don't let shyness waste your time.</p>
<h2 id="2-try-to-set-properties-once">2. Try to set properties once<a href="#2-try-to-set-properties-once">#</a></h2>
<p>When you know you have to do something (see above), try to <strong>do things once</strong>. This is really tricky in both HTML and CSS, languages that have no variables, and generally makes code reuse a pain. But it is possible.</p>
<p><strong>With CSS</strong>; set widths of elements once, and trust inner elements to fill their parent. That's the default behavior of block level elements, and you can set display: block, or width: 100% on most other elements. Don't set heights at all if you can avoid them, and let elements expand to fill their containers. Combine similar CSS selectors to avoid typing things twice, and make new ones for common properties when few properties differ. Use floats and clearing instead of absolute positioning, and you'll won't have to micromanage positions all the time.</p>
<p><strong>With HTML</strong>, make sure that you really know the template language. I've fighted with ASP.NET, JSP, JSTL, Smarty, WordPress Themes, RHTML, and Django's Templating Language, and now know enough about all of them to be productive. You should never have to type the same structure out twice, even in HTML. If your template language have loops, if-clauses and includes you really have no excuse to copy large chunks of HTML around. Refactor your HTML and make your own life easy.</p>
<h2 id="3-learn-your-text-editor">3. Learn your text editor<a href="#3-learn-your-text-editor">#</a></h2>
<p>When code reuse isn't possible, <strong>use search/replace</strong> in your favorite text editor.</p>
<p>Replacing all instances of one HTML tag name with another is about replacing "element>" with "element2>" (without the opening bracket). That way you replace both opening and ending tags at once. Check to see if your editor supports regular expressions in its search/replace tool. If it does you can save lots of time by learning it. Matching a HTML tag is "<[^>]+>", a starting angel bracket, one or more non-brackets, followed by an ending angel bracket. Naive regexps can make you match the starting bracket of one tag and the end of another, which makes for a mess.</p>
<p>There's lots of little tricks like that, if you learn them you save massive amounts of time.</p>
<h2 id="4-make-sure-your-environment-supports-you">4. Make sure your environment supports you<a href="#4-make-sure-your-environment-supports-you">#</a></h2>
<p>There's more than the text editor that you have to work with. One essential part of front-end development is trial and error. It sounds silly but no matter what your skill is, sometimes you must resort to trying and testing your way to a solution. With HTML and CSS, this means being able to <strong>quickly make a change, switch window, and see that change in the browser</strong>. If that cycle takes more that 5 seconds, you're losing valuable time.</p>
<p>Don't use a virtual machine (even if it's only for IE6) that you can't quickly Alt-Tab out of. If you're stuck using one, you need to have the text editor on that machine too. It's worth your time fixing it.</p>
<p>Don't accept build processes that makes you wait more than 5-10 seconds before you see your changes. With trial and error coding you will then waste 50% of your capacity doing nothing. Most often you can bypass this by copying just the HTML and CSS to the right place, without touching other source-code. I've managed to do this in all kinds of crappy environments, and it's always worth it.</p>
<p>So.</p>
<p>I hope some of the above can help you save some time each day. The little things add up you know. What's your best time-saver?</p>
Upside down text with CSS2008-06-26T22:34:31+02:002008-06-26T22:34:31+02:00http://friendlybit.com/css/upside-down-text-with-css/Emil StenströmPreviously I've talked about reversing text with CSS by simply setting a few CSS attributes. Today we will try another trick: turning text upside down. It's...
<p>Previously I've talked about <a href="/css/reverse-text-with-css-32-very-special-hex-digits/">reversing text with CSS</a> by simply setting a few CSS attributes. Today we will try another trick: turning text <strong>upside down</strong>.</p>
<p>It's actually possible using a simple CSS property and works cross-browser today. The property to use it "text-gravity" with a value of "inverse".</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-gravity: inverse"</span><span class="p">></span>
write upside down text
<span class="p"></</span><span class="nt">span</span><span class="p">></span>
</pre></div>
<p>… and this is the result:</p>
<p><span style="text-gravity: inverse">ʇxǝʇ uʍop ǝpısdn ǝʇıɹʍ</span></p>
<p>I'm really surprised to learn that so few people know about this property, and I recommend you to continue reading the <a href="http://www.fliptext.info/index.php">W3C specification of text-gravity</a>.</p>
<blockquote>
<p><strong>Update</strong>: Sorry, I lied :) The above is done with a UTF-8 character generator (see the link the the "specification" above). Amazingly, you can find that most characters have their upside down equivalent somewhere else in the huge Unicode alphabet. Neat trick :)</p>
</blockquote>
Feed readers should show comments2008-06-15T17:25:48+02:002008-06-15T17:25:48+02:00http://friendlybit.com/css/feed-readers-should-show-comments/Emil StenströmOne thing I've noticed lately is that I read fewer comments. It isn't that strange really: I read blogs using a feed reader and it doesn't show a links to...
<p>One thing I've noticed lately is that I read fewer comments. It isn't that strange really: I read blogs using a feed reader and it doesn't show a links to comments. I see a couple of reasons why comments are not cared for in feed readers:</p>
<h2 id="why-not-1-feeds-are-meant-to-be-fast">Why not #1: Feeds are meant to be fast<a href="#why-not-1-feeds-are-meant-to-be-fast">#</a></h2>
<p>Many subscribe to feeds to be able to get news before everyone else. And getting things fast means getting it before anyone else have commented. Why add a lot of zeros below each feed item?</p>
<p>But, it isn't unusual that <strong>I read posts that are a couple of days old</strong>. I don't read my feeds every day, rather every second or third day. In those days there are most likely comments on good posts, and of course I don't want to miss them. The older a post is, the more likely that it will have interesting comments.</p>
<h2 id="why-not-2-comments-are-hard-to-detect">Why not #2: Comments are hard to detect<a href="#why-not-2-comments-are-hard-to-detect">#</a></h2>
<p>Perhaps feed readers have a hard time detecting if there are comments to a post or not. Comments are not included in the post, so wouldn't they have to parse through the feed link for comments?</p>
<p>No, there is a tag called <code><wfw:commentRss></code>, that's possible to use in both Atom and RSS (If I'm not mistaken), that gives <strong>a link to the comment feed</strong>. That means feed readers could easily get the comments too. The best thing here is that all WordPress blogs (and others too) have it already. It's just a matter of using it!</p>
<h2 id="why-not-3-each-post-will-be-too-long">Why not #3: Each post will be too long!<a href="#why-not-3-each-post-will-be-too-long">#</a></h2>
<p>If there are 50 comments to a post, the item in the feed reader will be too long to read. That would also affect download time and therefore make things slow.</p>
<p>Yes, it will mean downloading more data, but you also get more information. <strong>Each feed reader is free to implement comments any way they like</strong>, and I doubt it will be to expand the original post with all 50 comments. I little link that expands comments (don't download any extra data until you expand)? Only show the first five, and a link to the page for more? There's lots of good options here.</p>
<h2 id="promote-contributions-more">Promote contributions more<a href="#promote-contributions-more">#</a></h2>
<p>Adding comments to your feed serves to promote your user's contributions even more, and I'm really surprised that not everyone does it. I'm using feed burner for <a href="/feed/">my feed</a> and can therefore use a feed flair (Click your feed / Optimize / FeedFlair / Comment count) to add a link to my comments at the end of the post. That's a first step.</p>
<p>What would be much better was if <strong>feed readers would get better at promoting comments</strong>. Could we get them to somehow?</p>
Avlyssna befolkningen (Swedish)2008-06-13T11:51:29+02:002008-06-13T11:51:29+02:00http://friendlybit.com/other/avlyssna-befolkningen-swedish/Emil Stenström(Eng: Sorry for writing this in swedish. Sweden is about to pass a law allowing the government to wiretap its citizens and I need to add a few things to the...
<p>(Eng: Sorry for writing this in swedish. Sweden is about to pass a law allowing the government to wiretap its citizens and I need to add a few things to the debate. The rest is in Swedish)</p>
<p>Sverige kommer på onsdag högst troligen rösta igenom ett lagändring om att FRA ska få avlyssna internet, istället för som tidigare skett radio och satellit. Det verkar vara mycket förvirring och prestige inblandad och jag tänkte göra ett försök att vidga debatten något.</p>
<p>Många som är för FRA-lagen påpekar att detta "egentligen inte är något nytt". Dom bara byter medium från radio till kabel. Är inte det fullständigt vettigt att även FRA ska få hänga med i teknikutvecklingen? Nej, för det finns en viktig skillnad: Vanligt folk använde inte radiovågor för att kommunicera tidigare, men dom använder internet för att kommunicera nu. Detta gör att FRA kommer att för möjlighet att avlyssna <strong>FLERA</strong> än tidigare, inte lika många. Gå inte på det argumentet, detta är inte bara en teknikuppdatering, det är en <strong>utökning av avlyssningen</strong>.</p>
<p>Politiker som är för lagen tänker också på FRA som en enhet istället för en grupp av enskilda människor. Skulle inte även du "bara prova" några sökningar och du satt där med en sökfält framför dig? Det är <strong>enskilda människor</strong> detta handlar om, inte en hel enhet som behöver göra fel, för att alla skyddsmekanismer som satts upp ska flyga åt fanders. Enskilda är det största hotet, men även FRA som enhet har gjort bort sig grundligt genom att medvetet bryta mot lagen tidigare. <strong>Systemet kommer med all säkerhet att missbrukas</strong>.</p>
<p>Många pratar också om den personliga integriteten, och det med all rätt, personlig integritet är viktigt. Vad väldigt få pratar om är <strong>företagskommunikation</strong>. Jag jobbar själv på ett internationellt konsultbolag som jobbar mycket mot svenska myndigheter. Vi skulle mycket väl kunna ha vår mailserver i Frankrike, där huvudkontoret ligger, vilket skulle göra att all vår kommunikation avlyssnas. Kommunikation som t.ex. skulle kunna handla om precis den myndighet som avlyssnar oss. Det håller inte.</p>
<p>FRA-lagen är en otroligt dum idé, som utökar möjligheterna för avlyssning av medborgarna, som bygger på att enskildas nyfikenhet inte blir för stor, och som inte bara påverkar den personliga integriteten utan också kan läcka personlig information om svenska företag.</p>
<p>Hjälp till, gör allt du kan för att övertyga dina politiker att rösta nej. <a href="http://knuff.se/">Knuffs framsida</a> gör det väldigt tydligt vad bloggsfären tycker, vad tycker du?</p>
<p><strong>Uppdaterat</strong>: Lagen gick igenom. Från årsskiftet kommer all datatrafik att avlyssnas, och en del även sparas. Vilket totalt misslyckande. Jag är grymt besviken.</p>
Sharepoint 2007 – insanely bad HTML2008-06-07T01:42:51+02:002008-06-07T01:42:51+02:00http://friendlybit.com/html/sharepoint-2007-insanely-bad-html/Emil StenströmSharepoint 2007 continues to amaze me with its terrible interface code. This is code you stumble over all over the place, both in places where you can hack...
<p>Sharepoint 2007 continues to amaze me with its terrible interface code. This is code you stumble over <strong>all</strong> over the place, both in places where you can hack your way around them, and in places where you just have to live with them. Some things are very hard to live with, let me show you:</p>
<p>ASP.NET developers made a decision once to include some hidden form fields, called viewstate, on all aspx pages. When deciding how to include those fields they chose an input with the type set to hidden. When the Sharepoint developers wanted to do something similar they decided on another route:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">"text"</span> <span class="na">name</span><span class="o">=</span><span class="s">"__spDummyText1"</span> <span class="na">style</span><span class="o">=</span><span class="s">"display:none;"</span> <span class="na">size</span><span class="o">=</span><span class="s">1/</span><span class="p">></span>
<span class="p"><</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">"text"</span> <span class="na">name</span><span class="o">=</span><span class="s">"__spDummyText2"</span> <span class="na">style</span><span class="o">=</span><span class="s">"display:none;"</span> <span class="na">size</span><span class="o">=</span><span class="s">1/</span><span class="p">></span>
</pre></div>
<p>So we have a visible textbox, hidden with CSS, that has a size of 1 character. No wait, we have two textboxes and they both have very descriptive names (NOT). What the heck were they thinking? Why not type="hidden", and remove size? Or, I know, don't add them at all, they are only dummy right? Note that they are empty.</p>
<p>Another strange interface decision is the one to include a skiplink in the page. Skip links are links that help screen readers (and others) to navigate to important areas quickly. There's many different ways to implement them, here's the Sharepoint way:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">A</span> <span class="na">href</span><span class="o">=</span><span class="s">"javascript:;"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"javascript:this.href='#mainContent';"</span> <span class="na">class</span><span class="o">=</span><span class="s">"ms-skip"</span><span class="p">></span>
</pre></div>
<p>The .ms-skip class positions it far off screen to the left, and the javascript… wait, javascript on a skip link? Why on earth did they not add #mainContent to the href attribute directly? Only they know…</p>
<p>Next in this post is a more philosophical piece of HTML. Look at this:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">span</span> <span class="na">dir</span><span class="o">=</span><span class="s">"none"</span><span class="p">><</span><span class="nt">table...</span><span class="p">></span>...<span class="p"></</span><span class="nt">table</span><span class="p">></span>
<span class="p"></</span><span class="nt">span</span><span class="p">></span>
</pre></div>
<p>I've heard about setting text direction to rtl (right to left), and ltr (left to right, for some eastern languages), but never to none. Where do text go that has no direction? Inwards? And what about having a table inside a span element?</p>
<p>ASP.NET also have user controls, a way to abstract out important pieces of code, to make reuse easy. Sharepoint of course uses this convenient tool regularly, and comes with a couple of useful ones:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">SharePoint:SPRememberScroll</span> <span class="na">runat</span><span class="o">=</span><span class="s">"server"</span> <span class="na">id</span><span class="o">=</span><span class="s">"TreeViewRememberScroll"</span>
<span class="na">onscroll</span><span class="o">=</span><span class="s">"javascript:_spRecordScrollPositions(this);"</span> <span class="na">Style</span><span class="o">=</span><span class="s">"overflow:</span>
<span class="s">auto;height: 400px;width: 150px; "</span><span class="p">></span> ...
</pre></div>
<p>In the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.sprememberscroll.aspx">documentation for SPRememberScroll</a> you can learn… absolutely nothing about it. It seems to strangely interact with a TreeView somehow, and even worse, it has a width and height! I guess it's good that it's separate from the TreeView itself, so we can remove it from there if we want to forget where we've scrolled to. What?</p>
<p>Sharepoint 2007, note the year there, also both have the classical spacer gif and a new one; the spacer span:</p>
<div class="highlight" data-language="HTML"><pre><span></span>Spacer gif:
<span class="p"><</span><span class="nt">td</span> <span class="na">width</span><span class="o">=</span><span class="s">"4px"</span><span class="p">><</span><span class="nt">IMG</span> <span class="na">SRC</span><span class="o">=</span><span class="s">"/_layouts/images/blank.gif"</span> <span class="na">width</span><span class="o">=</span><span class="s">4</span> <span class="na">height</span><span class="o">=</span><span class="s">1</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
Spacer span: <span class="p"><</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">"width: 3px; height: 5px;"</span><span class="p">></span> <span class="p"></</span><span class="nt">span</span><span class="p">></span>
</pre></div>
<p>Starting with the spacer gif: Luckily they have their width set twice, both on the image and the cell. Note the "4px" there, you can't use CSS units when you're writing HTML, HTML only knows about pixels. You're glad you wrote the width twice now, right? The spacer span is a fairly new thing I guess, the strange thing here is that you can't set a width and height on inline elements. It just doesn't work, sorry.</p>
<p>If you've built your user controls really bad, you might need a way to let people customize its HTML to make sense. Sharepoint has a couple of different ways to do this, one that they use themselves like this:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">SharePoint:DelegateControl</span> <span class="na">runat</span><span class="o">=</span><span class="s">"server"</span> <span class="na">ControlId</span><span class="o">=</span><span class="s">"PublishingConsole"</span>
<span class="na">PrefixHtml</span><span class="o">=</span><span class="s">"<tr><td colspan="</span><span class="na">4</span><span class="err">"</span> <span class="na">id</span><span class="o">=</span><span class="s">"mpdmconsole"</span> <span class="na">class</span><span class="o">=</span><span class="s">"ms-consolemptablerow"</span><span class="p">></span>"
SuffixHtml="<span class="p"></</span><span class="nt">td</span><span class="p">></</span><span class="nt">tr</span><span class="p">></span>">
</pre></div>
<p>If you manage to read that, you can see that they are injecting a table row somewhere inside their control (which of course generates a table). Is it just me that feels the urge to add an ending table tag to SuffixHtml just to see what happens?</p>
<p>Another truly interesting interface construct is the datepicker. It's one of these ordinary little calendar icons that opens in a little box and lets you pick a date. How did the Sharepoint guys (or girls) implement that?</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">...A</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">'clickDatePicker(<long id here>, <long url here>, ""); return false;'</span> <span class="p">></span>
<span class="p"><</span><span class="nt">IMG</span> <span class="na">src</span><span class="o">=</span><span class="s">"/_layouts/images/calendar.gif"</span> <span class="na">border</span><span class="o">=</span><span class="s">"0"</span> <span class="na">alt</span><span class="o">=</span><span class="s">"Select a date from the calendar."</span><span class="p">></span>
<span class="p"></</span><span class="nt">IMG</span><span class="p">></</span><span class="nt">A</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">IFRAME</span> <span class="na">SRC</span><span class="o">=</span><span class="s">"/_layouts/images/blank.gif"</span> <span class="na">FRAMEBORDER</span><span class="o">=</span><span class="s">0</span> <span class="na">SCROLLING</span><span class="o">=</span><span class="s">no</span>
<span class="na">style</span><span class="o">=</span><span class="s">"DISPLAY:none;POSITION:absolute; width:200px; Z-INDEX:101;"</span>
<span class="na">title</span><span class="o">=</span><span class="s">"Select a date from the calendar."</span><span class="p">></</span><span class="nt">IFRAME</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>...
</pre></div>
<p>Ok, lots of code to analyse here, and I've still only cut out the middle of a couple of nested tables. A link with an onclick that opens the datepicker is fairly standard, all parameters needed are encoded into a long url sent to that method. There's an image to click, with a strange img ending tag, but that could have been a mistake. The strange thing here is the iframe that points to a blank image. It's inserted into a table right <strong>between</strong> two cells (yes, you read that right). That's just insane. If you for some sensational reason have to use an iframe to display some HTML, output it javascript instead of just setting the src with js. Seriously people. Nice accessibility feature though, to have the alt text both on the image and on the iframe. Twice as accessible!</p>
<p>Another not-so-fine interface implementation is the following: They want to show a heading and a list of links. Personally, I would have used a heading tag, and an ul with links in. Sharepoint does it like this:</p>
<p><img src="/files/headingandlist.png" alt="Black heading, list items with yellow dot before" /></p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"margin-left: 4px;"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"level-header"</span><span class="p">><</span><span class="nt">span</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span> <span class="na">class</span><span class="o">=</span><span class="s">"headertitle"</span><span class="p">></span>Division<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"level-item-pos level-item level-bullet"</span><span class="p">><</span><span class="nt">span</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"<url>"</span><span class="p">></span>Information Technology<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">span</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"level-item-pos level-item level-bullet"</span><span class="p">><</span><span class="nt">span</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"<url>"</span><span class="p">></span>Research <span class="err">&</span> Development<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">span</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
...
</pre></div>
<p>They break their own scheme of prefixing all their classes with "ms-" (something that severely messed up my header), they repeat ids, they use only divs and spans, and inline styles.</p>
<p>Do I need to say more? Want to spread the word? <a href="http://www.reddit.com/info/6mepf/comments/">Vote on reddit</a>.</p>
New theme up for friendlybit.com2008-05-22T01:04:54+02:002008-05-22T01:04:54+02:00http://friendlybit.com/css/new-theme-up-for-friendlybitcom/Emil StenströmHi! If you're reading this blog through your feed reader, today is a good day to break out of it and have a look at the site. There's been several little...
<p>Hi! If you're reading this blog through your feed reader, today is a good day to break out of it and have a look at the site. There's been several little changes throughout, and I invite you to click around and explore things. <strong>Let me know if you find anything broken</strong>!</p>
<ol>
<li>Comments have moved up to the top and gotten more space. That includes the comment form which have been an insult to people wanting to comment. I'm hoping you reward me by correcting me even more often.</li>
<li>I'm using Google for my searches. Instead of trying to patch the builtin wordpress search I'm just linking to google from the header. It gives both faster and better results.</li>
<li>Design-wise it's much "lighter" than before. The old one felt hard and heavy, and didn't look to be as open as it in fact is.</li>
<li>Widgetized. I'm using wordpress widgets all over the place, which makes the administration of things like the "recent comments" easier. I just log in and change a number from the admin interface.</li>
<li>Fluid width (between 1000 and 1250 pixels).</li>
<li>Much nicer CSS, with a structure that you can actually follow.</li>
<li>I've <a href="/other/new-design-for-friendlybit/">promised</a> you the number of feed readers clearly visible, and I'm still going to get it done. But I'm not done yet.</li>
</ol>
<p>No matter what I will keep what I've always done with comments: I will read each and every comment you post, and I won't close articles for comments even though they are a year old. I will keep replying to (almost) all posts within a couple of days. I won't delete your comment just because I disagree with what you're saying, and I will go back and correct the original article with any errors you find.</p>
<p><strong>You</strong> are what makes this blog what it is. I could have written all my texts in word instead (and some of you probably wish I did sometimes), but that would have been totally meaningless. Feedback is what makes this blog go around.</p>
<p><strong>Thanks!</strong></p>
Web standards with ASP.NET2008-05-17T11:46:33+02:002008-05-17T11:46:33+02:00http://friendlybit.com/html/web-standards-with-aspnet/Emil StenströmGood interface code is a mix of CSS and HTML, and while most frameworks offer full control over the CSS, they rarely offer that for HTML. This article looks...
<p>Good interface code is a mix of CSS and HTML, and while most frameworks offer full control over the CSS, they rarely offer that for HTML. This article looks at how ASP.NET developers can help their interface developers gain that control. Disclaimer: I'm no .NET expert, but too few people write about this stuff, so I'll make a try.</p>
<h2 id="controls-that-keep-the-html-customizable">Controls that keep the HTML customizable<a href="#controls-that-keep-the-html-customizable">#</a></h2>
<p>Splitting pages into "controls" is a common way to build sites in ASP.NET. There's lots of different kinds of controls available, and I can't list all of them or name their differences. But I know I don't want to compile a .cs file every time a change some HTML. That pretty much rules out anything but <strong>user controls</strong> (as far as I know, but any kind of control that fills the above requirements would do). User controls have two sides, one for C# code (code-behind), and one for tags (HTML and calls to other controls).</p>
<p>There's also the issue of built-in stuff. ASP ships with many pre-built controls that help developers push out things quickly, the problem is that almost all of them neglect the HTML (DataList, GridView, …). They only allow setting a few properties, sometimes a CSS class, and assume that's OK. It isn't. I need full control over both the CSS and the HTML to be productive. There's one tag in particular is built with my kind of mindset, and that's the <strong>Repeater</strong>. A repeater is used like a for loop, but outputs no HTML itself. Instead it allows you to specify some code to output before the loop, inside the loop, every other step, and afterwards. That goes a long way, and that's often enough. If the predefined templates are insufficient, like if you want the last item to be rendered differently, you're out of luck.</p>
<p>I think I agree with the <a href="http://forums.asp.net/p/1239961/2263220.aspx">MVC Framework guys</a> in how to solve missing parameters of default controls and bad output: Use C# code inside your templates. Why is this different than the spaghetti code of old ASP? Because you only use layout related logic, nothing else. People tend to think mixing C# and HTML looks messy, but isn't it stranger to make two very different things look the same?</p>
<p>There's also tags like asp:hyperlink, asp:label, and so on; tags that essentially does exactly the same as the HTML they're hiding. Please don't use them, there's no abstraction layer needed for HTML.</p>
<h2 id="dont-repeat-yourself-not-even-in-the-interface">Don't repeat yourself - not even in the interface code<a href="#dont-repeat-yourself-not-even-in-the-interface">#</a></h2>
<p>Often when developers move from writing C# code to writing interface code they throw their coding skill out the window. You never copy a C# method just to make it output a different number - you make that number a parameter to the method instead. In the same way, you should never copy a piece of HTML from one place to another - move that code to a common masterpage or usercontrol instead. I've seen this many times, even from experienced developers. Never copy code, it makes for nightmare maintainance.</p>
<p>Also, use nested masterpages. So if you have three pages you need to build, and they have some code in common, you break that common code our into a masterpage. If two of the pages have even more in common you break that out into another masterpage, and let that one use the first one you made. Each Aspx page should only contain what makes it different from the other pages! Repeated HTML can also come in the form of small snippets of code, maybe 10 lines. You might not be able to break that out into a masterpage because it shows up all over the place. For those cases, break the snippet out into a usercontrol instead, and call that. Simple, and DRY.</p>
<h2 id="disable-viewstate">Disable viewstate<a href="#disable-viewstate">#</a></h2>
<p>HTTP is by default stateless. That means that each HTTP request to the server knows nothing about all the other requests made. For scalability and performance, that's a great thing. By default, ASP.NET makes web development stateful. Every form field you fill out gets saved into a hidden form field, called viewstate, and sent with every request. But I'm not talking about performance here, I'm talking about interface development:</p>
<p>To be able to save state across requests there's a hidden form field, and to be able to send that with every request there needs to be a form covering <strong>all</strong> your form fields. I can't help to think that handling statefulness in the HTML (the view) is the wrong place to do it. Aside from taking away some of my control over the HTML, it also has accessibility issues. JAWS, a popular screen reader, switch to a different reading mode when inside of forms, and while it's possible to get to all content inside a form, it's harder.</p>
<p>So, start by <a href="http://www.google.com/search?q=disable+viewstate">disabling viewstate</a> by default. If you must have it for a certain control, only enable it for that control.</p>
<h2 id="summary">Summary<a href="#summary">#</a></h2>
<p>There's lots of stuff you can do to make the HTML look better with ASP.NET, and that's a good thing. The bad thing is that it isn't that way by default. Now get out of here and go build some good HTML :)</p>
Use formats instead of microformats2008-05-17T12:29:26+02:002008-05-17T12:29:26+02:00http://friendlybit.com/html/use-formats-instead-of-microformats/Emil StenströmThe Semantic Web continues to break new ground, and Web 3.0 seems to be a term that people associate with it. In the backwaters of semantics, microformats...
<p>The <a href="http://www.w3.org/2001/sw/">Semantic Web</a> continues to break new ground, and <a href="http://en.wikipedia.org/wiki/Web_3">Web 3.0</a> seems to be a term that people associate with it. In the backwaters of semantics, microformats aims to develop standards to embed semantic information into XHTML. I can't help to think that's strange.</p>
<p>One of the <a href="http://microformats.org/about/">principles of microformats</a> is to "design for humans first, machines second". Still, almost all formats are about adding span tags and class or rel attributes to existing XHTML. Humans will never see those, or benefit from them, unless there's some kind of machine parsing done on top. Microformats were first built by people working with the blog search engine <a href="http://technorati.com/">technorati</a>, one of the reasons being to make it easier for technorati to aggregate data from those blogs. So machines it is.</p>
<p>Thing is, if you're going to give information to machines, why not use <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> instead of the equivalent microformat <a href="http://microformats.org/wiki/hcard">hCard</a>? hCard is just a translation of vCard into XHTML. vCards open in your e-mail program, allowing you to save the contact information there, hCards don't open anywhere. vCards are also just as easy (probably easier) to crawl and parse as microformats.</p>
<p>So what I'm saying is, <strong>could we please use real formats instead of microformats</strong>?</p>
<p><strong>Update:</strong> This article was too fuzzy, so let me clarify: This discussion is about embedded formats vs. formats. The "vs." come from the fact that lots of sites that implement microformats choose not to implement the corresponding format, which in some cases lead to people not being able to use the extra information.</p>
MSN blocks YouTube links2008-05-10T20:38:47+02:002008-05-10T20:38:47+02:00http://friendlybit.com/other/msn-blocks-youtube-links/Emil StenströmI'm not sure if there's some kind of big power struggle going on right now, but obviously MSN is blocking strings containing "www.youtube.com". It started...
<p>I'm not sure if there's some kind of big power struggle going on right now, but obviously MSN is blocking strings containing "www.youtube.com".</p>
<p>It started by me finding a funny youtube video (who didn't?), and tried sending it to a friend. Message back was that "Message could not be sent because of a network error". Some Googling brought up <a href="http://www.istartedsomething.com/20080510/windows-live-messenger-blocks-wwwyoutubecom/">other people with the same problem</a>.</p>
<p>Is this the first of a series of power struggles on the big Web 2.0 sites? Will Facebook block out LinkedIn links. Will Google (the owners of youtube) not link to Microsoft content? Interesting times we live in, indeed.</p>
<p><strong>Update:</strong> Seems it works again, where they trying to block some virus? Is blocking a major site the best way to do that? Was there really a virus or where they merely displaying their power? Will we get to know more? Not likely.</p>
Why the class name "wrapper" is so common2008-04-30T15:06:27+02:002008-04-30T15:06:27+02:00http://friendlybit.com/html/why-the-class-name-wrapper-is-so-common/Emil StenströmWe've all heard about how bad it is to use "left" and "yellow" as class names and ids. If you name an element "left", and then decide to move that element...
<p>We've all heard about how bad it is to use "left" and "yellow" as class names and ids. If you name an element "left", and then decide to move that element to the right, you have to go through all your pages and change that name. Too much work.</p>
<p>If you instead had called it "licenseAgreement", you would have been better off. Right? Perhaps not. Because we're forgetting about CMS:es. Those often have some kind of templates, where you as an interface developer define how the HTML should look. But as a interface developer, you have no idea of what kind of content editors will put into your templates. A couple of clicks later your "semantic id" is wrong.</p>
<p><strong>I think this is one of the reasons semantics hasn't gotten a hold of the CMS world</strong>. CMS:es have no idea of what kind of content people will store in them. Their main business goal is to make something generic, that doesn't assume semantics.</p>
<p>This is why "wrapper" is such a common class name.</p>
Top 3 articles of friendlybit.com (according to me)2008-04-11T20:29:14+02:002008-04-11T20:29:14+02:00http://friendlybit.com/other/top-3-articles-of-friendlybitcom-according-to-me/Emil StenströmRobert taunted me cause my blog was to inactive, so I thought I'd write something. As you might imagine, pushing me terribly to be creative like that isn't...
<p><a href="http://www.robertnyman.com/">Robert</a> taunted me cause my blog was to inactive, so I thought I'd write something. As you might imagine, pushing me terribly to be creative like that isn't a good way to get good posts up, so I thought I'd just point to some existing articles instead. The selection is not based on popularity, ratings, number of visitors, comments, or anything like that. It's based on me. :)</p>
<p>Now. First up is <strong>my post on <a href="/css/dear-justin-timberlake/">Justin Timberlake</a></strong>. Surprised? There's lots of good things to say about that one. It was very fun to write, I love writing letters to totally unlikely people, and that was what I did. Secondly, there's a couple of great comments on that post from people that seriously thought there was a chance that Justin would read it. Isn't that like, desperate? Damn right it is. Thirdly, a couple of weeks after that post <a href="http://www.robertnyman.com/">Robert</a> pulled me aside for a chat: "Don't get upset by this, cause I just want to ask something". "Yes?", I replied, seeing he was somewhat uncomfortable. "Well… Are you gay? I mean that post about Justin some time ago…". What?! Can't you declare your love to a man nowadays without being called gay?! My god! :) (Update: Girlfriend is telling me to point people to the disclaimer below that post. Yeye.)</p>
<p>Number two of my favorite posts is <strong>my little <a href="/html/web-standards-hero-episode-1/">webstandards hero</a> thingie</strong>. I just got bored of the regular blog format and decided I should try something else. A comic book sounded like a good plan and I just started writing, making up little twists along the way. I like the end result, but I didn't get that many readers (according to stats). Perhaps the webdev world wasn't ready for plastic figures yet. Sad…</p>
<p>Third, and last, on this toplist is <strong>of course <a href="/css/real-hackers-dont-use-css/">Real hackers don't use CSS</a></strong>. Again, I'm experimenting with style, and that one actually worked :) It still gets lots of visitors, and hopefully some nice laughs from people. My faviourite response was people from reddit, that were <strong>really</strong> upset that I used the term hackers like I did. How could I abuse it like that? How could I smear the fine shimmer of gold that emits from someone that can write Perl really well? Because I'm a mean evil person. Of course.</p>
<p>What can I learn from my own favorite posts? That I should experiment with style more. You'll see more of that, I can assure you!</p>
Fixing Sharepoint 20072008-03-27T23:22:53+01:002008-03-27T23:22:53+01:00http://friendlybit.com/other/fixing-sharepoint-2007/Emil StenströmI'm sorry for all the Sharepoint 2007 posts lately, if you're not interested, just skip to the next post :). Anyway. The Sharepoint team recently announced...
<p>I'm sorry for all the Sharepoint 2007 posts lately, if you're not interested, just skip to the next post :). Anyway. The Sharepoint team recently announced further support of an addon called Accessibility Kit for SharePoint (abbreviated AKS) in a blog post about the future of Sharepoint on their official blog.</p>
<p>I thought I'd comment on the future plans, and get a bit more constructive and point to things that are rather easy to fix. Perhaps I can affect what gets focus in the next version? With a release cycle of 30-34 months (!), any changes won't get implemented anytime soon, but I guess getting on the right track is a first step.</p>
<h2 id="shift-focus-from-accessibility-to-customization">Shift focus from accessibility to customization<a href="#shift-focus-from-accessibility-to-customization">#</a></h2>
<p>First of all, I've only briefly touched accessibility on my two posts about Sharepoint (<a href="/html/default-html-in-sharepoint-2007/">Default HTML in Sharepoint 2007</a> and <a href="/css/sharepoint-2007-from-an-interface-developers-view">Sharepoint 2007 from an interface developer’s view</a>. But to me, accessibility is the second step, being able to customize things, is the first. Let me repeat that <strong>I care more about being able to customize the Sharepoint interface, than the default interface being accessible</strong>. Right now, large parts of the interface are locked down, deep inside of the Sharepoint core. If I could customize things, I could correct the accessibility issues myself. I really think the focus should be customization first, and accessibility second.</p>
<h2 id="but-its-possible-to-customize-some-parts">But it's possible to customize some parts!<a href="#but-its-possible-to-customize-some-parts">#</a></h2>
<p>Lots of people have commented on my previous posts saying that it in fact <em>is possible</em> to get Sharepoint to produce valid HTML. It's possible to some extent, by rewriting all masterpages and many default controls that come with Sharepoint. Of course you can build a good interface if you only use Sharepoint for storage, and build the interface from scratch. But that's skipping a lot of the things you bought Sharepoint for, all the existing components!</p>
<p>And you still can't change the collaborative parts. And as soon as you want to add content to the site or change settings, you're back in lock-in, no control, Sharepoint interface land.</p>
<h2 id="deliver-as-a-service-pack-not-an-addon">Deliver as a service pack, not an addon<a href="#deliver-as-a-service-pack-not-an-addon">#</a></h2>
<p>So, back to the announcement. I think it's a shame that AKS is delivered as an add-on, and not as a service pack to Sharepoint. Accessibility is a user concern (they are the ones that need stuff done), not one that developers desperately need. So the focus should be to push this one to as many users as possible, and make it very easy to enable it for developers. A service pack would accomplish that much more effectively than an addon does. Most developers won't even know the addon exists!</p>
<h2 id="control-adapters-are-not-the-best-solution">Control adapters are not the best solution<a href="#control-adapters-are-not-the-best-solution">#</a></h2>
<p>In the announcement is something called Smart adapters, from what I understand a way to automate replacing .NET controls with your own controls. So when Sharepoint calls that breadcrumb control, you redirect it to call your own breadcrumb instead. The problem here is that I have to rebuild the whole control from scratch, instead of just changing how it's output.</p>
<p>Instead, if Sharepoint could expose a .NET List (the breadcrumb links) to me, I could decide the rendering myself. That's customization!</p>
<h2 id="dont-repeat-yourself-use-master-pages">Don't repeat yourself, use master pages<a href="#dont-repeat-yourself-use-master-pages">#</a></h2>
<p>More suggestions of changes: One of the biggest annoyances in Sharepoint is the bad implementation of master pages. Sharepoint only allows each site to have one Master page set, so you really can't use your master pages for controlling things like number of columns. Putting that in the masterpage would means you would need to use that number of columns on all your pages. In Sharepoint, you instead have to wash out the bare essentials that all your pages have (a html and body element?), and set that in the masterpage. If two of your pages are similar, copy/paste the code between them. Terrible! What I want to be able to do, is to set several masterpages per site, and use inheritance between those masterpages. That's fundamental master page concepts, that Sharepoint is lacking.</p>
<h2 id="organization-of-css-and-javascript">Organization of CSS and Javascript<a href="#organization-of-css-and-javascript">#</a></h2>
<p>When you ship code to your customers (Sharepoint is a framework, so Microsoft is essentially selling code to developers), you need to make sure that code is readable, and understandable. That does not only apply to C# code, it applies to the full interface as well. That's simply not the case with Sharepoint. There's two humongous files, core.css and core.js, where most CSS and Javascript have been poured into, with no consideration of organization or namespaces. There's no indication how certain C# components interact with the CSS and Javascript and very very little documentation (often added after the fact, by annoyed developers like me). This just <strong>have to change</strong>, we need organization, modules, separation. We need an interface that we can understand without reverse engineering!</p>
<p>Another thing, releasing controls that are thought to be reused, really mean that they need to work in <a href="http://www.quirksmode.org/css/quirksmode.html">standards mode</a>. All controls, even webparts. It isn't reasonable to have to <a href="http://blogs.msdn.com/feldman/archive/2007/11/18/sharepoint-doctype-and-master-pages.aspx">patch things inside your Javascript chaos</a> to make basic things work! It isn't reasonable to have to patch CSS for standards mode either. It shouldn't have relied on quirks mode in the first place!</p>
<h2 id="examples-are-good-but">Examples are good, but…<a href="#examples-are-good-but">#</a></h2>
<p>The announcement also mentions examples. Releasing examples of how to make Sharepoint validate, conform to WCAG 2.0 AA (really?), or any other standard, can of course be of help. A lot more help than no documentation. But it's also pushing over the problem to the customers. "We couldn't make our product validate, but you can fix that, but doing this, this, then this, and that". A default site shouldn't have 200 errors out of the box, you can do better than that.</p>
<h2 id="wysiwyg-editor-and-firefox">WYSIWYG editor and Firefox<a href="#wysiwyg-editor-and-firefox">#</a></h2>
<p>The Accessibility Kit also mentions a new WYSIWYG editor, "aRTE", that can be used instead of the default editor. It's of course well needed, the default editor doesn't work at all outside of Internet Explorer, and I really doubt that it's accessible. So why is this released as an addon? You've built a better content editor, give it to people!</p>
<p>Also, the new editor takes you another step closer to supporting Firefox. You're pretty near, but not being able to edit content in a CMS with Firefox really is bad. That should be the baseline. Really, I could understand if the ActiveX über-COM Silverlight Vista integration didn't work, but editing content, or maybe interacting with webparts? To cling to Internet Explorer in this day and age is not going to work.</p>
<h2 id="in-summary">In summary<a href="#in-summary">#</a></h2>
<p>I hope that some of the improvement areas mentioned in this post will be taken into consideration in the development of the next version of Sharepoint. My tone is harsh, but that's because I've really been slowed down my Sharepoint in my daily work. Customers complain because tiny interface changes takes days to complete. I hope you can see past my frustration, and see that there are big areas where you really can improve how Sharepoint work. I'm willing to help pointing in (what I think is) the right direction.</p>
Style tables with CSS2008-03-14T01:10:28+01:002008-03-14T01:10:28+01:00http://friendlybit.com/css/style-tables-with-css/Emil StenströmI don't deal too much with tables. Not because I don't want to but because clients hardly ever want to use them. My guess is that they are too hard to...
<p>I don't deal too much with tables. Not because I don't want to but because clients hardly ever want to use them. My guess is that they are too hard to create with todays WYSIWYG editors, and therefore get left out. It happens though that I have one or two static tables I need to style, and then I get to use a couple of my tricks.</p>
<p><strong>All of the examples below work across browsers. Including IE6.</strong></p>
<ul>
<li><a href="#gradient">Add a gradient to your cells</a></li>
<li><a href="#spacing">Remove the space between the cells with CSS</a></li>
<li><a href="#width">Obey the set width</a></li>
<li><a href="#columns">Styling columns</a></li>
</ul>
<h2 id="gradient">Add a gradient to your cells<a href="#gradient">#</a></h2>
<p>One easy way to make tables look better is to add a <a href="http://9rules.com/blog/2006/08/a-gradient-tutorial/">subtle gradient</a> to the cells. That's easy to do. But make sure you also set a background color with one of the edge colors from the gradient, and use the top or bottom keyword. You never know the height of your cells when people zoom the text.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">td</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#2B2B3C</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="sx">item_gradient.gif</span><span class="p">)</span><span class="w"> </span><span class="kc">repeat-x</span><span class="w"> </span><span class="kc">bottom</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<h2 id="spacing">Remove the space between the cells with CSS<a href="#spacing">#</a></h2>
<p>When designing tables you rarely want the ugly double border between two cells that appear when you set a border on td. Neither do you want the space in between them… Many believe the only way to remove that space is to use the cellspacing and cellpadding attributes in HTML. You don't:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">table</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border-collapse</span><span class="p">:</span><span class="w"> </span><span class="kc">collapse</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">td</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">px</span><span class="w"> </span><span class="kc">solid</span><span class="w"> </span><span class="kc">silver</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>See? No ugly HTML attributes needed.</p>
<h2 id="width">Obey the set width<a href="#width">#</a></h2>
<p>Many of you have probably seen tables that do not stay within the width you have set on them. It can be long words or sometimes URLs that are wider than what can fit. By default, the browser puts content before style, and therefore expands the table to show the content. But what many don't know is that you can change them to always obey the set width:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">table</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">table-layout</span><span class="p">:</span><span class="w"> </span><span class="kc">fixed</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Easy, and now the table will be 100px, no matter what.</p>
<h2 id="columns">Styling columns<a href="#columns">#</a></h2>
<p>Sometimes you want to style some columns differently than all other cells, and I've seen that most people add a special class to each of the cells in that column. Wouldn't it be nice if there was a way to just specify the class once? There is!</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">table</span><span class="p">></span>
<span class="p"><</span><span class="nt">col</span> <span class="na">class</span><span class="o">=</span><span class="s">"first"</span><span class="p">></span>
<span class="p"><</span><span class="nt">col</span> <span class="na">class</span><span class="o">=</span><span class="s">"second"</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Header 1<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Header 2<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Cell 1<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Cell 2<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">table</span><span class="p">></span>
</pre></div>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">col</span><span class="p">.</span><span class="nc">second</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="kt">px</span><span class="o">:</span>
<span class="p">}</span>
</pre></div>
<p>Convenient isn't it? There's one thing you should know though… The col attribute only allows <a href="http://www.w3.org/TR/CSS21/tables.html#columns">four attributes</a>: Border, Background, Width, and Visibility. What the heck? Well, there is performance issues with implementing more complex things so W3C decided not to include it. So what if you need to set, say, text-align on a column? You can be clever:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">col</span><span class="p">.</span><span class="nc">second</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">text-align</span><span class="p">:</span><span class="w"> </span><span class="kc">right</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">td</span><span class="p">:</span><span class="nd">first-child</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nt">td</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">text-align</span><span class="p">:</span><span class="w"> </span><span class="kc">right</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>The above works because IE allows setting more properties on columns than the spec allows (<a href="http://ln.hixie.ch/?start=1070385285&count=1">Hixie explains it well</a>). Firefox on the other hand, ignores the set text-align, but instead allows you to use a sibling selector to select the "second td after the first one" (you can add another "+ td" to select the third one, and so on…). Voilá! Cross browser column specification.</p>
<p>That's all for now, did you know all of them?</p>
IE8 is back on the standards track2008-03-04T07:55:45+01:002008-03-04T07:55:45+01:00http://friendlybit.com/html/ie8-is-back-on-the-standards-track/Emil StenströmYesterday the Internet Explorer Team showed a big change in attitude. Listening to developer feedback about IE8, they changed their mind, and now IE8 will...
<p>Yesterday the Internet Explorer Team showed a big change in attitude. Listening to <a href="/css/ie8-and-doctype-switching/">developer feedback about IE8</a>, they <a href="http://blogs.msdn.com/ie/archive/2008/03/03/microsoft-s-interoperability-principles-and-ie8.aspx">changed their mind</a>, and now IE8 will render standards mode pages using the latest and greatest it can offer.</p>
<p>This is not only a sane way to approach standards, but it's also a way to say "We're listening and are open to change based on your feedback" (Although saying the reason is the new Interoperability standards and not user feedback is rather weak).</p>
<p>This move is great for both for the web in general and for the Internet Explorer Team. Let there be celebration!</p>
Documenting CSS2008-02-27T23:55:00+01:002008-02-27T23:55:00+01:00http://friendlybit.com/css/documenting-css/Emil StenströmJust like all other programming the CSS needs documentation. I'm afraid I'm rather bad at it: the times I'm lucky I've been able to document by simply...
<p>Just like all other programming the <strong>CSS needs documentation</strong>. I'm afraid I'm rather bad at it: the times I'm lucky I've been able to document by simply talking to the developer taking over, and the unlucky times I've left no documentation at all. Talking directly is of course superior to everything else, you don't waste time explaining things that are obvious (differs from person to person), but you don't always have that luxury. So what I thought I'd do is list things I think are important to document, for the times when you won't be available for answering questions.</p>
<p>Don't be fooled to think all projects are alike. Sometimes you're under tremendous stress just to get the basic CSS up and running; it isn't reasonable to expect the same kind of documentation then… But most often you have an hour extra to just jot down a couple of lines about your interface.</p>
<ul>
<li><strong>How is the CSS file(s) structured?</strong> When you build large sites you often end up with over 1000 lines of CSS, and if you don't structure them, you'll end up with a mess. Even if you DO have a structure, it takes a lot of time to figure out someone else's code. To give you some ideas of your own, I wrote about how I <a href="/css/how-to-structure-large-css-files/">structure my CSS</a> previously. You don't have to use that one, just be conscious about your choice, and document it.</li>
<li><strong>Where do I add new styles?</strong> Either it's obvious from the previous structure or you need to make it obvious how to add new stuff. What if I'm adding a deviation from how a certain section looks, should I put it near that section's styles, or near all other deviations? This question is especially important on sites with lots of campaign components with custom CSS. Trust me, your cleverly crafted structure will become a mess if you miss answering this question.</li>
<li><strong>What can I do with existing styles?</strong> To make sure design ends up in the CSS and not in the HTML there needs to be some kind of overview of all available classes. Else people are going to hack things and try to duplicate your code. How do you handle columns, clearing, quotes, and floated images? Did you think of it yourself or do I have to add my own code? A good way might be to make a document where you tie the different classes to how they look when used.</li>
<li><strong>How are different browsers handled?</strong> Struggling through browser hacks is a real pain in the ass, unless those hacks are properly documented. What browsers do you try to support, and which of them have you tested in? Did you plan for the future?</li>
<li>(Optional) <strong>Web standard basics</strong>. Working with web standards is rather different than working the old (table based) way . So if you know that oldschool developers will work with your code (are you sure they won't?), it could be a good idea to shortly summarize the modern web mindset. I recommend using a lot of links here, not to waste time; people are very different in what they know.</li>
</ul>
<p>If you've answered the questions able you've come a long way. Your code is understandable, and will stay in shape for much longer. Not to mention when you're looking at some code in a year, thinking: "Who wrote this shit?! It's a mess!", and then figure out it was you.</p>
<p>Now, is there anything essential I'm missing, that you want to add?</p>
Default HTML in Sharepoint 20072008-02-26T00:27:33+01:002008-02-26T00:27:33+01:00http://friendlybit.com/html/default-html-in-sharepoint-2007/Emil StenströmAs I've said before, I've been spending time with Sharepoint 2007 recently. The HTML it produces is really bad, and today I thought I show you just how bad....
<p>As I've said before, I've been <a href="/css/sharepoint-2007-from-an-interface-developers-view/">spending time with Sharepoint 2007</a> recently. The HTML it produces is really bad, and today I thought I show you just how bad.</p>
<p>Sharepoint 2007 has been "updated" to support <a href="http://msdn2.microsoft.com/en-us/library/wtxbf3hh.aspx">masterpages</a>, a concept from .NET 2.0. Sharepoint's implementation of masterpages has several problems, but none of them even come close to the biggest problem of them all: default.master.</p>
<p>Default.master is the page that ships with Sharepoint and is used everywhere by default. A quick glimpse at it would make any seasoned web developer feel sick, and I quickly replaced it with something homemade. If you keep reading you will see why. Let's get going with the first line:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">HTML</span> <span class="na">xmlns:o</span><span class="o">=</span><span class="s">"urn:schemas-microsoft-com:office:office"</span> <span class="na">dir</span><span class="o">=</span><span class="s">"ltr"</span> <span class="na">__expr-val-dir</span><span class="o">=</span><span class="s">"ltr"</span><span class="p">></span>
</pre></div>
</div><p>Things start out really bad, without a doctype on the first line. This mean that all default pages will render in <a href="http://en.wikipedia.org/wiki/Quirks_mode">quirks mode</a>, making rendering unreliable across browsers. Next they set an XML namespace, which after some googling points to very <a href="http://msdn2.microsoft.com/en-us/library/ms875215(EXCHG.65">thorough documentation (pun intended)</a>.aspx). So they mean that it's an XHTML document? No, because XHTML has lowercase tags, and here they use uppercase. The attribute <span class="incorrect"><code>__expr-val-dir</code></span> just doesn't exist.</p>
<p>A hardcoded link to the 4000 line "core.css" (filled with classnames you have to override by hand), and five external hardcoded javascripts then follow. Then 30 lines of inline CSS and javascript. Then comes the next real beauty, the body tag:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">BODY</span> <span class="na">scroll</span><span class="o">=</span><span class="s">"yes"</span> <span class="na">onload</span><span class="o">=</span><span class="s">"javascript:</span>
<span class="s"> if (typeof(_spBodyOnLoadWrapper) != 'undefined')</span>
<span class="s"> _spBodyOnLoadWrapper();"</span><span class="p">></span>
</pre></div>
</div><p>The funniest thing here is the scroll attribute. Let me paraphrase <a href="http://html.com/attributes/body-scroll/">html.com</a> (found through quick googling):</p>
<blockquote>
<p>SCROLL, which is only recognized by MSIE, indicates if there be scroll bars on the page. The default value is YES, so the only reason to use SCROLL is to set it to NO. SCROLL serves little purpose except to confuse and annoy readers by removing scroll bars which are there for a good reason.</p>
</blockquote>
<p>I couldn't have said it better myself. There's no reason, whatsoever, to use the scroll attribute. Ever. Especially with "yes" set. <em>Pause for deep breaths</em>. Then we have the inline javascript. Did you know that you could put javascript: inside of onload? Despite all odds, it seems to work. <code>_spBodyOnLoadWrapper()</code> is by the way Sharepoint's way of letting you add javascript to pages. You first do a <span class="incorrect"><code>_spBodyOnLoadFunctionNames.push("YourFunctionName");</code></span>, and then that code will get run. Insane.</p>
<p>Then we have the typical ASP.NET form, encapsulating the whole page, followed by 18 hidden HTML fields (including the infamous viewstate). Directly afterwards, we have a 60 line mix of inline and external javascript, contained in 7 different code blocks (two that's missing the type and language attribute).</p>
<p>The next discovery can be found three <em>nested tables</em> later:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">span</span> <span class="na">id</span><span class="o">=</span><span class="s">"TurnOnAccessibility"</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: none"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"SetIsAccessibilityFeatureEnabled(true);</span>
<span class="s"> UpdateAccessibilityUI();return false;"</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span>
<span class="na">class</span><span class="o">=</span><span class="s">"ms-skip"</span><span class="p">></span>Turn on more accessible mode<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">span</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"javascript:this.href='#mainContent';"</span> <span class="na">href</span><span class="o">=</span><span class="s">"javascript:;"</span><span class="p">></span>
class="ms-skip" AccessKey="J">Skip to main content<span class="p"></</span><span class="nt">a</span><span class="p">></span>
</pre></div>
</div><p>I'll wait until you regain consciousness. Hi, welcome back. Yes, they are using <span class="incorrect"><code>display: none</code></span> and javascript calls to enable "accessibility mode". I mean seriously, screen readers ignore things with display: none set, and we can certainly not always trust that javascript is enabled. I also love the skiplink, and how it sets its own href attibute to an internal link. Note how this code is (mostly) lowercase.</p>
<p>And this is where it starts to get ugly. Every Sharepoint page has a Personal menu and a Site menu on it, containing things you want to do with your account or the current site. Fair enough. This is the (rather lengthy) code for the Personal menu:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">"display:none"</span><span class="p">></span>
<span class="p"><</span><span class="nt">menu</span> <span class="na">type</span><span class="o">=</span><span class="s">'ServerMenu'</span> <span class="na">id</span><span class="o">=</span><span class="s">"zz3_ID_PersonalActionMenu"</span>
<span class="na">largeIconMode</span><span class="o">=</span><span class="s">"true"</span><span class="p">></span>
<span class="p"><</span><span class="nt">ie:menuitem</span> <span class="na">id</span><span class="o">=</span><span class="s">"zz4_ID_PersonalInformation"</span>
<span class="na">type</span><span class="o">=</span><span class="s">"option"</span> <span class="na">iconSrc</span><span class="o">=</span><span class="s">"/_layouts/images/menuprofile.gif"</span>
<span class="na">onMenuClick</span><span class="o">=</span><span class="s">"javascript:GoToPage([url]);return false;"</span>
<span class="na">text</span><span class="o">=</span><span class="s">"My Settings"</span> <span class="na">description</span><span class="o">=</span><span class="s">"Update your user information, regional settings, and alerts."</span>
<span class="na">menuGroupId</span><span class="o">=</span><span class="s">"100"</span><span class="p">></</span><span class="nt">ie:menuitem</span><span class="p">></span>
... [three more "ie:menuitem"] ...
<span class="p"></</span><span class="nt">menu</span><span class="p">></span>
<span class="p"></</span><span class="nt">span</span><span class="p">></span>
<span class="p"><</span><span class="nt">span</span> <span class="na">title</span><span class="o">=</span><span class="s">"Open Menu"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"zz8_Menu_t"</span> <span class="na">class</span><span class="o">=</span><span class="s">"ms-SPLink ms-SpLinkButtonInActive"</span>
<span class="na">onmouseover</span><span class="o">=</span><span class="s">"MMU_PopMenuIfShowing(this);MMU_EcbTableMouseOverOut(this, true)"</span>
<span class="na">hoverActive</span><span class="o">=</span><span class="s">"ms-SPLink ms-SpLinkButtonActive"</span>
<span class="na">hoverInactive</span><span class="o">=</span><span class="s">"ms-SPLink ms-SpLinkButtonInActive"</span>
<span class="na">onclick</span><span class="o">=</span><span class="s">" MMU_Open(byid('zz3_ID_PersonalActionMenu'), MMU_GetMenuFromClientId('zz8_Menu'),event,false, null, 0);"</span>
<span class="na">foa</span><span class="o">=</span><span class="s">"MMU_GetMenuFromClientId('zz8_Menu')"</span>
<span class="na">oncontextmenu</span><span class="o">=</span><span class="s">"this.click(); return false;"</span> <span class="na">nowrap</span><span class="o">=</span><span class="s">"nowrap"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">id</span><span class="o">=</span><span class="s">"zz8_Menu"</span> <span class="na">accesskey</span><span class="o">=</span><span class="s">"L"</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"javascript:return false;"</span>
<span class="na">style</span><span class="o">=</span><span class="s">"cursor:pointer;white-space:nowrap;"</span>
<span class="err">...</span> <span class="err">[</span><span class="na">five</span> <span class="na">more</span> <span class="na">eventhandlers</span><span class="err">]</span> <span class="err">...</span>
<span class="na">menuTokenValues</span><span class="o">=</span><span class="s">"MENUCLIENTID=zz8_Menu,TEMPLATECLIENTID=zz3_ID_PersonalActionMenu"</span>
<span class="na">serverclientid</span><span class="o">=</span><span class="s">"zz8_Menu"</span><span class="p">></span>
Welcome Emil Stenström<span class="p"><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/_layouts/images/blank.gif"</span> <span class="na">border</span><span class="o">=</span><span class="s">"0"</span> <span class="na">alt</span><span class="o">=</span><span class="s">"Use SHIFT+ENTER to open the menu (new window)."</span><span class="p">/></span>
<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">img</span> <span class="na">align</span><span class="o">=</span><span class="s">"absbottom"</span> <span class="na">src</span><span class="o">=</span><span class="s">"/_layouts/images/menudark.gif"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">span</span><span class="p">></span>
</pre></div>
</div><p>There's several things worth a note here (in a bad way). The menu tag Sharepoint uses is in fact a real HTML tag, <a href="http://www.w3.org/TR/html401/struct/lists.html#h-10.4">deprecated in HTML 4.01</a>. Inside of that we have a tag called ie:menuitem that I really can't understand. What on earth is ie:menuitem? Did they intentionally not make it work in other browsers? Everything is wrapped inside a <span class="incorrect"><code>display: none;</code></span> As you see, tags are also cluttered with event handlers, both real and made up ones. The contextmenu is blocked twice, and a spacer gif is used to add alternate text to the link. The menu icon is hardcoded into everything.</p>
<p>It goes on in the same manner, with tables with the "TOPLEVEL" attribute (and no value), divs with a WebPartId set, PlaceHolder tags rendered directly out in the HTML (instead of parsed by ASP.NET), to end with 200 lines of mixed inline javascript and css. Everything embedded in several layers of nested tables.</p>
<h2 id="in-conclusion">In conclusion<a href="#in-conclusion">#</a></h2>
<p>Default.master contains the worst code I've ever seen, and it's really disappointing to see that from a product with "2007" in it. Microsoft have failed in every possible way when it comes to the interface code, and I believe the only way out is to rebuild Sharepoint from scratch (not likely to happen). Having to work with Sharepoint is a real pain, and I honestly don't recommend it to anyone. Put your curiosity to use into something more interesting, like the <a href="http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx">ASP.NET MVC Framework</a> instead. Thanks for listening.</p>
Worth a look: DOMAssistant2008-02-25T21:30:31+01:002008-02-25T21:30:31+01:00http://friendlybit.com/js/worth-a-look-domassistant/Emil StenströmA couple of months ago Robert Nyman showed me a javascript library he had built, DOMAssistant, and proceeded to use it successfully in one of our projects....
<p>A couple of months ago <a href="http://www.robertnyman.com/">Robert Nyman</a> showed me a javascript library he had built, <a href="http://domassistant.com/">DOMAssistant</a>, and proceeded to use it successfully in one of our projects. I wasn't amused. How could a tiny homebuilt little hack compete with my favorite, the almighty jQuery?</p>
<p>I whined, and said I really liked the CSS-selector syntax that jQuery has. So <a href="http://www.robertnyman.com/2007/12/17/domassistant-25-released-css-selector-support-new-ajax-methods-and-more-goodies-added/">he added support for CSS1, CSS2, and CSS3</a>. The bastard.</p>
<p>After a while he started getting doubts about if he really could compete with the big names, being supported by lots of people. But instead of giving up he got himself <a href="http://domassistant.com/about/">a team of his own</a>. The famous <a href="http://www.456bereastreet.com/about/">Roger Johansson</a> being one of them. There went that argument, damnit!</p>
<p>I pointed out the jQuery was very small, only 15 kb! He pointed out that DOMAssistant is half that size, 7 kb. That's smaller than most images. Aaaargghh!</p>
<p>I said that jQuery is much faster than anything I've seen. He showed me the <a href="http://www.domassistant.com/slickspeed/">slickspeed</a> test, showing that his framework was indeed faster than all the others. How could he do that? Well, he explained, by using the browser optimized XPath and querySelectorAll support in browsers.</p>
<p>I had one card left to play, a somewhat ugly one. "Animations?" I almost wispered. "No…" came the reply back. But as he saw me straighten my back, getting ready to proclaim victory, he contiuned "… but it's being worked on, and coming in the next release". Damn you Robert, it seems I just have to give it a try…</p>
IE8 and Doctype switching2008-01-26T17:44:50+01:002008-01-26T17:44:50+01:00http://friendlybit.com/css/ie8-and-doctype-switching/Emil StenströmThe topic of this week has been IE8s new rendering mode, and the strange way to trigger it. As usual, I've decided not to comment right away, and instead...
<p>The topic of this week has been IE8s new rendering mode, and the strange way to trigger it. As usual, I've decided not to comment right away, and instead first read what others are saying and try to form an opinion.</p>
<p>I believe the best articles that talks about the switch are these:</p>
<ol>
<li><a href="http://www.b-list.org/weblog/2008/jan/23/legacy/">Legacy</a>, by <span class="person-name">James Bennet, puts this move in a bigger context. I believe his most important conclusion is that Microsoft are now clearly positioning themselves towards big old corporate intranets, reiterating "Don't break the web".<br /> </span></li>
<li><a href="http://www.andybudd.com/archives/2008/01/has_internet_ex/">Has Internet Explorer Just Shot Itself in the Foot?,</a> by Andy Budd, talks about how Microsoft marginalizes their own browser. Most people won't know about the switch, and end up in IE7 mode, so there's no real need for anyone to upgrade. IE7s rendering engine needs to be with us, forever.</li>
<li><a href="http://diveintomark.org/archives/2008/01/23/microsoft-koan">Microsoft koan</a>, by Mark Pilgrim, elegantly points out that strange code (unknown doctypes, including html5) will be rendered in standards mode, and ordinary code (proper doctype) will be rendered in IE7 mode. Seems twisted?</li>
</ol>
<h2 id="the-real-strangeness">The real strangeness<a href="#the-real-strangeness">#</a></h2>
<p>What I can't understand in all of this is how IE7-specific sites can be such big of a problem. Because that what all of this fuss is really about. That's why we need a new switching mode and they need to ship the IE7 rendering engine with IE8.</p>
<p>So, now there's a couple of different sites.</p>
<ul>
<li><strong>IE6 specific sites.</strong> My guess is that these are the majority of sites out there. These will break as much in IE8 as they did in IE7. "Don't break the web" does not apply to these sites.</li>
<li><strong>IE7 specific sites</strong>. These are much fewer and got updated rather recently (badly, to work only in IE7). The new switch is there for these sites. With the switch these sites won't break.</li>
<li><strong>Sites built to the standards</strong>. These were also updated rather recently, but unlike the above sites they were built to the standards. Fixes for IE6 and IE7 were properly only sent to just those browsers, and will <em>not</em> be sent to IE8 (conditional comments anyone?). If you targeted IE7 with your conditional comment, IE8 will not get that fix, breaking these type of sites. Well, unless IE8 will execute IE7 conditional comments, when that engine does the rendering.</li>
</ul>
<p>So let's look back at the previous articles, keeping in mind the IE team mantra: "<em>Don't break the web</em>", the very reason why this fix exists.</p>
<p><strong>First article</strong> (1): My guess is that many corporate intranets belong in the first group of sites. They haven't been updated in a while, and won't be either. This group of sites will be just as unhappy with IE8 as they were with IE7. This can't be about those sites. IE team mantra: "<em>Keep breaking the web just as much as we broke it before</em>".</p>
<p><strong>Second article</strong> (2): This switch will increase the number of sites in the IE7 specific group. This will be at the expense of the standards group. When a developer not knowing about the switch sees that his site works in IE7 and IE8 (which will be the same), he will stop working on it. IE team mantra: "<em>Freeze the web to IE7</em>".</p>
<p><strong>Third article</strong> (3): Since unknown doctypes will send IE8 into standards mode, there will be even more breakage than before. What? Well, sites with broken doctypes, that previously sent IE6 and IE7 into quirks mode and relied on that, will break. IE Team mantra: "<em>Break the web</em>".</p>
<p>Additionally, modern developers that don't read the IE blog, and don't know about the new switch, will keep getting IE7s strange behaviour on their sites. And since the switch also can be made via a HTTP header, even copying the full HTML and CSS of a site might break it when looking at it locally. IE team mantra: "<em>Make people read our blog, or go insane trying to develop to the standards</em>".</p>
<h2 id="what-it-all-comes-down-to">What it all comes down to<a href="#what-it-all-comes-down-to">#</a></h2>
<p>This is a terrible idea, both technically and in how it was presented. If the same idea had been presented in a more open manner, "<em>we're thinking about solving this problem like this… what do you think?</em>", people would have been much more willing to help, and had probably came up with a better solution.</p>
<p>WaSP really acted badly by not first talking to the community, or at least discussing things internally, and instead just presented how IE8 will be built. Also, since this won't help developing standards based websites, and instead help IE7 specific sites, I'm not sure what the WaSP has to do with this issue whatsoever.</p>
<p>On the constructive side of things, I think the <strong>best way forward for IE8 is to change the switch to be opt-in, letting IE7 specific sites switch to IE7 rendering if they want to</strong>. That's makes sure IE7 sites that break are easy to fix, and does not break havoc on the rest of the web. Don't set the default to worse rendering than you can produce.</p>
<p>With the above change, I'm looking forward to another modern web browser, IE8.</p>
Sharepoint 2007 from an interface developer’s view2008-01-20T12:10:42+01:002008-01-20T12:10:42+01:00http://friendlybit.com/css/sharepoint-2007-from-an-interface-developers-view/Emil StenströmLike Cameron Moll (Skinning Sharepoint and Pointedly unskinnable), I've been working with Sharepoint 2007 (aka MOSS) recently, and I hope you don't mind me...
<p>Like Cameron Moll (<a href="http://cameronmoll.com/archives/2007/05/skinning_ms_sharepoint_with_st/">Skinning Sharepoint</a> and <a href="http://cameronmoll.com/archives/2007/10/sharepoint_2007_pointedly_unskinnable/">Pointedly unskinnable</a>), I've been working with Sharepoint 2007 (aka MOSS) recently, and I hope you don't mind me posting a few articles about my work here. I've found far too few blog posts that really go to the depth in explaining how things really work. I'll try to do that here, but I hope you can respect my wish that this does not turn into a helpdesk.</p>
<h2 id="quotcustomizationquot">"Customization"<a href="#quotcustomizationquot">#</a></h2>
<p>Let's start. <strong>Sharepoint 2007 very, very hard to customize</strong>. If your job is to customize the interface in any major way, you have a lot of work ahead of you. You might think you're a much better interface developer than me, but you still have a lot of work ahead of you. You need to accept that.</p>
<p>When you read about Sharepoint 2007 on other sites you will find that people are really ecstatic about it. Just check the comments on how to <a href="http://planetwilson.blogspot.com/2007/09/sharepoint-2007-colour-color-calendar.html">customize the calendar</a>. Reading carefully you will find that he's comparing it with Sharepoint 2003, not with other products, or even a standard ASP.NET site. That's a big difference. Sharepoint 2003 was much worse, but that does not mean things are good now. This is a common pattern, people that like Sharepoint compare it to the previous version, not with better ways of doing things.</p>
<p>As most CMS:es, Sharepoint gets sold to customers that don't know programming. They see a product that can handle all the features they want: blogs, wikis, forums, calendars, document libraries, workflows, and so on. All features you could ever want is included, from what is called "out of the box". The problem is that the system is built so that all of those "out of the box" features are hard to customize. Things like changing how the wiki renders, is really hard. Often it's easier to rebuild that feature from scratch, than customizing what Sharepoint ships.</p>
<p>This is the main reason, from my point of view, that you should pick another CMS.</p>
<h2 id="specifics">Specifics<a href="#specifics">#</a></h2>
<p>I don't believe you trust me on my words, so I thought I'd be more specific now, and talk about the issues that make Sharepoint 2007 hard to work with (customize). Let me stress that these are not all the issues, just the major ones that an interface developer has to tackle.</p>
<h3 id="development">Development<a href="#development">#</a></h3>
<p>From what I've read from larger projects, the recommended development environment for a Sharepoint site is a virtual machine. For us, we needed a 36 Gb image, a size that required me to get a new external hard drive, just to store it. Also, running in a virtual machine means that you only can use about half of your RAM, which means everything gets slow. As if that wasn't enough, a new virtual machine means you have to reinstall all your programs, browsers, plugins again. Web development shouldn't have to be like that.</p>
<h3 id="accessibility">Accessibility<a href="#accessibility">#</a></h3>
<p>Sharepoint has gotten a lot of bashing for not being accessible, so they've added some features to account for that. Some of those are really good individually, but looking at the general mess that is the HTML that Sharepoint spits out, the pretty page above fades in importance. One major problem is that you still need <strong>javascript enabled</strong> for many of the accessibility features. Enabling "Accessibility mode", among other things, makes dropdown menus appear as new windows (popups) instead of dynamically writing HTML to the page. And this is after they "fixed" it.</p>
<h3 id="page-size">Page size<a href="#page-size">#</a></h3>
<p>A standard Sharepoint site uses lots of default Javascript and CSS in two files called core.js and core.css. All in all they add up to over 250 kb. Yes, that's not a misspelling or extra zero, a default page in sharepoint takes at least 250 kb. This is not counting the HTML, a huge, table-ridden, inline-javascripted, mess of things.</p>
<p>If you go through lots of trouble, you can strip those files out, but that means you can't use any default components. Since much of Sharepoint depend on those, you don't really want to go that way. It's a mess, and Microsoft themselves recommend you try to <a href="http://msdn2.microsoft.com/en-us/library/bb727371.aspx#MOSS2007OptPerfWCM_PagePayloadSmallisGood">remove some of it</a> to boost performance. Preferably by using AJAX to load the js file later. Seriously.</p>
<h3 id="javascript-and-browser-dependencies">Javascript and Browser dependencies<a href="#javascript-and-browser-dependencies">#</a></h3>
<p>Except from core.js, the javascript is spread out all over the place. As usual in many CMS:es, javascript is not treated as a real programming language, so there's no structuring whatsoever. Sometimes it's script tags, sometimes inline, sometimes external mini files, and most often automatically generated code. It's a real mess, and is a big reason for the HTML size being so large. Many of the scripts do not work in browsers other than IE, which means you really need IE to properly use the admin interface.</p>
<p>From the browser compatability info you can read that there are level 1 and level 2 browsers:</p>
<blockquote>
<p>"Level 2 web browsers support all of our basic functionality so that users can both read and write in our content sites, perform site administration, etc. Some functionality may not be available, some functionality may be available in a more limited form, and some visual rendering may not be as optimized as our Level 1 browsers. We also will not support Level 2 web browsers on the Central Administration site."</p>
</blockquote>
<p>These are the Level 2 browsers: Firefox, Netscape, Safari. Opera isn't even in the list. Is this the new, modern way, of handling cross browser compatibility?</p>
<h3 id="changing-the-css">Changing the CSS<a href="#changing-the-css">#</a></h3>
<p>I previously said that most CSS is included in a file called core.css. The file in itself if huge, with thousands of class names, and no structuring whatsoever. Heather Solomon has made an attempt to make things workable by <a href="http://www.heathersolomon.com/content/sp07cssreference.htm">making images of what each class specifies</a>. It's not even nearly a complete reference, and helps some, but using <a href="http://getfirebug.com/">Firebug</a> is a faster way. Another thing the CSS sheet above does, is show how completely unorganized the CSS is. Have a look at it.</p>
<p>As with core.js you can't really remove core.css, since lots of built-in functionality depends on it. So what you need to do is start deciding which of those rules you need to overwrite and which not. Have fun!</p>
<p>To add to the insult, if you just add your own CSS as an external file and try to link to that on your own pages, core.css is appended as the last stylesheet in the source code. This of course means that all your changes get overwritten, and you need to hack around things by using the <link> tag directly (instead of sharepoint's own csslink-control), or add your custom files via the admin interface. Since core.css is just a list of simple class names, you can also use <a href="http://www.htmldog.com/guides/cssadvanced/specificity/">CSS Specificity</a> to make your rules count, but that isn't mentioned in any of the troubleshooting blog posts. None the less, it's tedious do work around.</p>
<h3 id="share-point-and-master-pages">Share point and Master pages<a href="#share-point-and-master-pages">#</a></h3>
<p>Most of Sharepoint is upgraded to use .NET 2.0, and its concept of Master pages and aspx pages. For those of you that don't develop in .NET the two can be explained as a templating mechanism, where each Master page has general placeholders where you can insert aspx pages. In each aspx page you specify one master page, and all of the placeholders you want to fill with content. It's a pretty good system.</p>
<p>Sharepoint taps into this system by making up two strings "~masterurl/custom.master", and "~masterurl/default.master", that you use instead of specifying your own masterpages. Users then specify masterpages in the admin interface, potentially breaking the entire site. Also, Sharepoint assumes there's just one masterpage per site, so if you thought you could use one masterpage for twocolumn layouts, and another for threecolumn layouts, you're wrong. The solution here is to break out of the Sharepoint way and hardcode real urls instead of doing things the Sharepoint way.</p>
<p>There's also things you can't change. The admin interface has a masterpage called application.master, which controls pretty much everything that has to do with built-in Sharepoint things. You don't ever change this file, since it's quite easy to seriously break things then. The problem is that this file also specify the look and feel of the admin interface, and if you're building a site where people are expected to add stuff, they will spend time in the admin interface. There isn't a good way around this, and you probably end up just changing some colors via CSS and let it be.</p>
<h3 id="default-net-controls">Default .NET controls<a href="#default-net-controls">#</a></h3>
<p>The default master pages that ship with Sharepoint is horrendous and I'll post more details about them in a later post. But even if you roll your own master pages from scratch you still have the standard .NET-problem with controls. Using controls in .NET is a way to package functionality that you can easily add to your pages. A developer just needs to copy a DLL file, and call the control, optionally sending in some parameters. Easy.</p>
<p>The problem with this approach is that a control consists both of logic and HTML. So if you want some built-in logic that renders, say, the breadcrumb trail, you also get the HTML the author of the control deemed appropriate. In Sharepoint, a breadcrumb trail can be a doubly nested table, with display: none; controls to enable accessibility, and a doubly span nested link. It's just a terrible mess, but there's no other way to get to the breadcrumb logic, except from building a new control from scratch. Be prepared to work with terrible HTML.</p>
<h2 id="in-summary">In summary<a href="#in-summary">#</a></h2>
<p>If you want to examine the points above by yourself, there's a MOSS example site up at <a href="http://www.wssdemo.com/default.aspx">wssdemo.com</a>.</p>
<p>This article is a interface developer view at Sharepoint 2007. If you look at the system from other viewpoints, I'm sure there are good things there. That's not my point. What I'm trying to say is that <strong>Sharepoint 2007, is beyond repair when it comes to interface customization</strong>, and you should do everything in your power to avoid working with it. If I can give one interface developer the arguments to convince a customer to pick another system, this article was worth it. Thanks for reading.</p>
IE8 renders the acid 2 test2007-12-20T00:27:21+01:002007-12-20T00:27:21+01:00http://friendlybit.com/css/ie8-renders-the-acid-2-test/Emil StenströmI'm not sure why I don't see that many people talking about the fact that IE8 renders the acid 2 test perfectly now. It really seems Microsoft is starting...
<p>I'm not sure why I don't see that many people talking about the fact that <a href="http://blogs.msdn.com/ie/archive/2007/12/19/internet-explorer-8-and-acid2-a-milestone.aspx">IE8 renders the acid 2 test perfectly</a> now. It really seems Microsoft is starting to move forward again, after starting to feel some pressure from the open source world. Will they be able to pick up the speed needed to get 96% marketshare again? Time will tell.</p>
<blockquote>
<p><strong>Update</strong>: Good <a href="http://channel9.msdn.com/showpost.aspx?postid=367207">interview about IE8</a> on channel9.</p>
</blockquote>
Future of web standards (my take)2007-12-20T00:35:18+01:002007-12-20T00:35:18+01:00http://friendlybit.com/css/future-of-web-standards-my-take/Emil StenströmStuart Landridge sums up the ongoing debate about the future of CSS. My thoughts on this are that we should: Let browser makers run loose with implementing...
<p>Stuart Landridge sums up the <a href="http://www.kryogenix.org/days/2007/12/17/reigniting-the-browser-wars">ongoing debate about the future of CSS</a>. My thoughts on this are that we should:</p>
<ol>
<li><p>Let browser makers run loose with implementing <strong>new features</strong>, based on feedback from web developers.</p>
</li>
<li><p>Have a standard body (or some other group) that look at those <strong>existing features</strong> and see how they can be standardized.</p>
</li>
<li><p>Have browsers change their implementation of the <strong>features to match</strong> what the standards body proclaims.</p>
</li>
</ol>
<p><strong>Step 1</strong> stops the bad idea that is to have a committee of people do innovation work. You need people both that know what web developers want and what is possible to implement. Browser makers do this.</p>
<p><strong>Step 2</strong> makes sure the wild features that browser makers have played with get usable on real sites. To be usable a certain feature needs to be usable across (a majority of) browsers, and web developers of today know this. Before reaching this stage features will be played with, but not used on production sites.</p>
<p><strong>Step 3</strong>. Browser makers having implemented a feature differently from what the spec suggests need to change their implementation to match that of the standard. This step means that the standards body need to have the trust of the browser makers.</p>
<p>For the features of a certain browser, this means that a feature will move from "experimental", when it's played with, and to "standardized", when there is a spec and the feature conforms to it. Browsers need to specify this somehow.</p>
<p>I believe this is a much saner process than what is going on right now. Let's try it.</p>
New design for friendlybit coming up2007-12-06T22:44:00+01:002007-12-06T22:44:00+01:00http://friendlybit.com/other/new-design-for-friendlybit/Emil StenströmHi. I just wanted to tell you that I'm now working on the new friendlybit. I've listened to your previous comments, and these are the changes I'm going to...
<p>Hi. I just wanted to tell you that I'm now working on the new friendlybit. I've listened to your <a href="/other/the-future-of-friendlybitcom/">previous comments</a>, and these are the changes I'm going to make/not make:</p>
<ul>
<li><strong>Blog format stays</strong>, no community. You're damn conservative (something like 95% percent said to keep it a blog).</li>
<li><strong>More compact writing</strong>. I'll skip more of the fluffy wording, and concentrate on what I want said. That means shorter posts.</li>
<li><strong>WYSIWYG-editor</strong> inside WordPress (my blogging tool) gets turned on. This might make the HTML somewhat worse, but It makes my job easier, so I'll try anyways.</li>
<li><strong>Paid links gets removed</strong>. I previously sold links on the frontpage and got like $200 a month from them. I've now removed them, since:<ol>
<li>It seems to be hip inside the Googleplex to kick on people making money from other things than AdSense.</li>
<li>I have no idea if the PageRank drop from PR6 to PR4 is caused by them, but I'm still going to hope that was the case. We'll see.</li>
<li>To show to myself that blogging isn't about money. Now I most definitely don't blog for the money.</li>
</ol>
</li>
<li><strong>Number of feed readers</strong> will be used as a way of seeing if I do my job or not. This will also be shown at the top of all pages, so you will be able to follow them too.</li>
<li><strong>Comments will be central</strong>, as <a href="/other/the-future-of-friendlybitcom/#comment-26790">Jesse Skinner suggested</a>. For now, I'm just moving them up, above the fold, but we'll see where we end up.</li>
<li><strong>New design</strong> underway. As a token of me caring for you (and me wanting to steal your skills), I thought I'd post a screenshoot of it here:</li>
</ul>
<p>But. This damn layout is to narrow, so I'll just paste a link instead: <a href="/files/friendlybit_single_export.png" data-no-instant>New friendlybit design</a>. Some ideas (all changable if you give me good reasons): <a href="/files/friendlybit_single_export.png" data-no-instant></a></p>
<ul>
<li>It will be flexible width, between 800 and 1024 pixels.</li>
<li>Content and comments will each take up approx 50% of the page width, so you'll get plenty of eyeballs on your comments.</li>
<li>I don't know the height of the columns, so I'll just let them expand downwards as long as they need to be.</li>
<li>I won't make it work in IE6 (on purpose). This is for my own satisfaction, and seriously, any decent web developer should already have something better. Stats say 60% Firefox, 16% IE7, and 14% IE6. Please upgrade people. I will test it in the latest version of Opera (4.2%) and Safari (4.5%). Why? Because I want more users with good browsers, and fewer with bad. And since this is a personal blog, I can choose. Yay!</li>
</ul>
<p>Now. Do I have to tell you I want your feedback on that?</p>
CSS3 Media queries instead of the media attribute2007-11-21T18:21:50+01:002007-11-21T18:21:50+01:00http://friendlybit.com/css/css3-media-queries-instead-of-the-media-attribute/Emil StenströmIn my previous post about the media attribute I talked about how strange the media attribute is, and that its usefulness isn't that obvious. As a followup I...
<p>In my previous post about the media attribute I talked about <a href="/css/media-attribute/">how strange the media attribute is</a>, and that its usefulness isn't that obvious.</p>
<p>As a followup I want to point you to an article that Russell Beattie wrote about <a href="http://www.russellbeattie.com/blog/css3-and-the-death-of-handheld-stylesheets">CSS3 media queries</a>. Media queries are a way to <strong>check the capabilities</strong> of a user-agent instead of checking what kind of media type it claims to be. This makes a lot of sense to me. Does it really matter if someone is using a small computer screen or a big mobile phone? What about if they use a <a href="http://www.youtube.com/watch?v=CZrr7AZ9nCY">big ass table</a>? (aside from the pun, I really think <a href="http://www.youtube.com/watch?v=rP5y7yp06n0">Microsoft surface</a> is cool)</p>
<p>Checking for capabilities of a certain user-agent makes much more sense: "if available width larger than 200px, show two columns instead of one". If they are dynamically evaluated (I don't know if they are), they allow you to build truly dynamic layouts, that work virtually everywhere. That's what I call accessible layouts.</p>
<p>An interesting parallel is comparing checking user-agent strings and <a href="http://developer.apple.com/internet/webcontent/objectdetection.html">object detection in javascript</a>, and the media attribute and media queries. I believe media queries is the natural next step. Today, the different types of media have started to mix; just look at TV:s and computers, or handheld computers and mobile phones. <strong>The type of media is not as important, capabilities are</strong>.</p>
<p>Although queries do not solve all of the questions I put forward in the previous post, they do pose an interesting alternative. Agreed?</p>
<p>(<a href="http://www.w3.org/TR/css3-mediaqueries/">CSS3 Media queries</a> are as a standard currently a candidate recommendation (which means it's safe to implement), and is currently <a href="http://www.css3.info/preview/media-queries/">supported by Opera 9 and Safari 3</a>.</p>
<blockquote>
<p><strong>Update</strong>: Opera 9.5 evaluates the queries dynamically, Safari does not, thanks <a href="http://simon.html5.org/">zcorpan</a>)</p>
</blockquote>
Media attribute – what have you done for me lately?2007-10-29T00:06:54+01:002007-10-29T00:06:54+01:00http://friendlybit.com/css/media-attribute/Emil StenströmI've been thinking for a while about the media attribute on link tags. Some people might find that thinking deep thoughts about HTML attributes is kind of...
<p>I've been thinking for a while about the media attribute on link tags. Some people might find that thinking deep thoughts about HTML attributes is kind of strange, but I know you, my dear readers, know the feeling ;)</p>
<p>An example, just so I know we're on the same page:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">link</span> <span class="na">href</span><span class="o">=</span><span class="s">"style.css"</span> <span class="na">media</span><span class="o">=</span><span class="s">"handheld"</span>
<span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/css"</span><span class="p">></span>
</pre></div>
<p>This makes sure devices that support the handheld media type (mobile phones?) should load that stylesheet, but no others. It seems simple doesn't it? By using a simple attribute you can style things differently for certain devices. But there's several things to keep in mind, that actually make this attribute a lot less useful.</p>
<h2 id="problem-number-1-presentation-and-content-are-cou">Problem number 1: Presentation and content are coupled<a href="#problem-number-1-presentation-and-content-are-cou">#</a></h2>
<p>One of the big selling points of CSS is the separation of presentation from content. And while I believe that's still a good thing to have, not everyone agrees about it's usefulness. Some time ago Jeff Croft wrote an article about how unusual it is to only change the CSS and not the HTML of a site. While he's mostly making a point of why we should use a certain CSS framework, there's a good point hidden there: Right now it isn't possible to separate things completely.</p>
<p>Designers have of course known this for centuries. They will tell you: you need to adapt the design to the content you're designing. If you're building a site for a shampoo, you might use water and bubbles in your design. If you build a web development blog, you use an image of blueish sky… ehm… Well, you get the point. Good design adapts to the content. They are coupled.</p>
<p>You can't just switch out the content and expect the design to still work. Sure, you can make small adjustments, and make these available as alternate stylesheets, but larger changes just doesn't work. The problem with the media attribute is that it's made for big design changes (switching media), but with no changes in content. How often can you just restyle a word document to get a powerpoint slide? What about converting that slide to something nicely viewable on a mobile phone? That's what the media attribute is there for.</p>
<p>My point is: switching to another media needs much more than just a change in design. You need to change the content to fit that media too. And if you change the content, why not change what stylesheet you link to? This is why I rarely use the "handheld" or "projection" values.</p>
<h2 id="problem-number-2-load-time">Problem number 2: Load time<a href="#problem-number-2-load-time">#</a></h2>
<p>You could think that the browser only loads the one stylesheet that matches the media it's currently showing. Not true. All stylesheets, <a href="http://www.phpied.com/delay-loading-your-print-css/">no matter what media</a> they are tied to, are loaded at startup.</p>
<p>This means that the more media types you account for, the longer the load time for any of them will be. Very annoying.</p>
<h2 id="problem-number-3-user-agent-support">Problem number 3: User agent support<a href="#problem-number-3-user-agent-support">#</a></h2>
<p>While being able to design for specific user agents might sound like a good idea, the media attribute still requires user agents to support it. If a large part of user agents refuse to apply your style using the media attribute, why not use another method directly? Just to get an idea of how messy support currently is, you can read the <a href="http://css-discuss.incutio.com/?page=HandheldStylesheets">css-discuss summary of the handheld problems</a>:</p>
<blockquote>
<p>"Some current phones apply "screen" styles as well as "handheld" styles, others ignore both, and in some cases the phone carrier runs pages through a proxy that strips styles out even if the phone could recognize them, so it's a crapshoot figuring out what will get applied"</p>
</blockquote>
<p>As you see, the value of the media attribute isn't entirely obvious. Sure, you might be able to use it for print with good results, but that's not all it's there for. Right?</p>
@media Ajax London, here I come2007-10-28T23:09:37+01:002007-10-28T23:09:37+01:00http://friendlybit.com/css/media-ajax-london-here-i-come/Emil StenströmJust a short note that I'll be attending @media Ajax London, 19th-20th November. If you see me, come by and say hello!
<p>Just a short note that I'll be attending <a href="http://www.vivabit.com/atmediaajax/">@media Ajax London</a>, 19th-20th November. If you see me, come by and say hello!</p>
Manipulating innerHTML removes events2007-09-26T23:24:04+02:002007-09-26T23:24:04+02:00http://friendlybit.com/js/manipulating-innerhtml-removes-events/Emil StenströmOthers have written about this before, but I thought I'd mention it again, just so you don't miss it. Aleksandar Vaci? found it while playing with tables...
<p>Others have written about this before, but I thought I'd mention it again, just so you don't miss it. Aleksandar Vaci? found it while playing with tables and their cells. I found it when <a href="http://www.robertnyman.com/">Robert</a> and I played with nested lists. It works the same across browers. Let me show a quick example:</p>
<p>You have a paragraph tag that contains a span that you want to make clickable.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">p</span> <span class="na">id</span><span class="o">=</span><span class="s">"para"</span><span class="p">></span>
<span class="p"><</span><span class="nt">span</span> <span class="na">id</span><span class="o">=</span><span class="s">"clickspan"</span><span class="p">></span>This is clickable.<span class="p"></</span><span class="nt">span</span><span class="p">></span>
But this is not.
<span class="p"></</span><span class="nt">p</span><span class="p">></span>
</pre></div>
<p>To make it clickable you don't do any fancy stuff, you just add it with onclick:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">span</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsById</span><span class="p">(</span><span class="s2">"clickspan"</span><span class="p">);</span>
<span class="nx">span</span><span class="p">.</span><span class="nx">onclick</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">alert</span><span class="p">(</span><span class="s2">"You clicked the span!"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>All fine. You click the span and it just works. But then you remember something. You want to add some text to the end of the paragraph, and you decide to do this with javascript. You add the following line to the end of the script:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"para"</span><span class="p">);</span>
<span class="nx">p</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s2">" Some extra text"</span><span class="p">;</span>
</pre></div>
<p>You try clicking the span again, and it doesn work. You scratch your hair, you bite your nails, you scream of desperation and anger. It still doesn't work. It seems manipulating an element by using innerHTML removes all events from that element, and all children. Here's a <a href="/files/innerHTMLevents/" data-no-instant>live example</a>. I thought you should know.</p>
I’m an interface developer2007-08-20T23:17:55+02:002007-08-20T23:17:55+02:00http://friendlybit.com/css/im-an-interface-developer/Emil StenströmIn his latest post Roger Johansson asks the question Are we designers or developers?. I have a simple answer for that. None of them. Let me explain: First...
<p>In his latest post Roger Johansson asks the question <a href="http://www.456bereastreet.com/archive/200708/are_we_designers_or_developers/">Are we designers or developers?</a>. I have a simple answer for that. <strong>None of them</strong>. Let me explain:</p>
<p>First we have these people calling themselves <strong>developers</strong>. And boy do they know programming… and math… and… no that's all. Many have a masters degree in computer science, a degree that pretty much tells you that they once gave five years of their lives to programing, how cool is that!? It's not unusual to find people that <a href="http://xkcd.com/55/">think in those terms</a> too. You can recognize them by their 10 year old, unmatched, clothes and you'll rarely talk more than 1 minute with them. Very efficient.</p>
<p>Then we have the <strong>designers</strong>. Either real females, or people very close to females, that just can't stop talking about this abstract thingie-thongie that just like, you know, exploded in a big burst of colors and like… "EHEM! Sorry!", you hear them say, regaining consciousness and flying back to earth. Their clothes, at least you think they are clothes, often look like they where meant for something else. Perhaps for building steel pumps, or killing animals… or both. Well, at least these clothes are matched… or very purposefully not at all matched (not at aaaall like the developers). You can talk with these people for hours, probably even days, and still only touch upon the delicate topic of "a glass of water". Oh, and they "create" things too. Very deep.</p>
<p>So where the heck does the <strong>interface developer</strong> come into all of this? Well, imagine you have a real project at hand. Real people that need some new website to do their work. Real deadlines, money that switches hands. Smiling business people that promises things and shake hands. Seems like something you know of?</p>
<p>Now, imagine bringing a developer and a designer together in a room, for like a month, working together with this new website. Concentrate hard and try to see the images before your very eyes. Will they accomplish anything?</p>
<ol>
<li><strong>Hell no!</strong> In 5 minutes they will have started arguing about who should be the first one to open the door, and in what way. One talking about the most efficient way to turn the handle, and the other one defending herself by talking about cosmic beams from Saturn. After the first day the developer will have sore cheeks, after being constantly bitch slapped while hiding under his desk. The third day the designer will sit shaking in a corner after the electric shock induced by the steel helmet the developer built. None of them will survive the fourth day, let alone the project.</li>
<li><strong>Very yes!</strong> When you meet them after the month has passed you find two harmonic people that smiles to each other and really seem to have connected. They explain to you that the demonstration will be in two parts, first the designer and then the programmer. The designer shows you an app that really touches you, at least you think so, although you not fully understand it. The programmer shows you the other part of the app, one that instantly shows the number 369. They finish the presentation and look at you. You stand up, walk out, lock yourself into a nearby free conference room, and shout with all the power in your lungs: "HOW THE F*#CK AM I GOING TO DO MY TAXES WITH THIS SHIT?!#". When you come back you find them congratulating each other for making the deadline.</li>
</ol>
<p>You see? There's something missing there. Some kind of link between the two. Someone that can walk into a room with two screaming people and calmly say: "Hey, you both kinda run linux (SuSE vs. Mac OS X), and have a "cold" desktop background (default plain blue vs. modern interpretation of <a href="http://en.wikipedia.org/wiki/Image:Vasnetsov_Snegurochka.jpg">Vasnetsov Snegurochka</a>), what a coincidence!?". There needs to be someone that can walk into the same room the next day and explain that they are talking about two different kinds of "abstract methods". There needs to be a link.</p>
<p>But there's more: An interface developer is silly enough to learn languages that doesn't even have variables. Even though he know that his code will be sent as uncompressed plaintext and will be rendered by broken excuses for programs, he won't cry himself to bed every night.</p>
<p>He will also gladly adapt a design to something it wasn't really intended for, and he even will make it look somewhat good. He will skip adding those fabulous shadows, to make the deadline on time, and still think of himself a good person.</p>
<p>You see, even though "interface" reflect the visual graphic things, and "developer" relate to hard logic code, <strong>interface developers</strong> are real people, not a combination of two halves. I am one.</p>
The future of friendlybit.com2007-08-06T19:57:42+02:002007-08-06T19:57:42+02:00http://friendlybit.com/other/the-future-of-friendlybitcom/Emil StenströmIt's vacation time and you're allowed to lean back and just relax. A blog it's always there though, you post to it on your spare time, and as soon as you...
<p>It's vacation time and you're allowed to lean back and just relax. A blog it's always there though, you post to it on your spare time, and as soon as you have some a little glitch in your schedule you need to consider blogging. It's a full time job.</p>
<h2 id="current-situation">Current situation<a href="#current-situation">#</a></h2>
<p>I use Friendly Bit as a way to express <strong>my thoughts and ideas</strong> about web development. Why? Partly because I'm passionate about the web, passionate to make it a better place. I want people to see the possibilities it holds, and make use of it in the best way possible. I want people to see the web from different angles, sometimes from an accessibility standpoint and sometimes from the eyes of a designer. I want people to think about what they are doing, every line of code they are putting down, instead of typing with auto-pilot turned on.</p>
<p>That's me, trying to get my point out to you. What's equally important is <strong>your feedback</strong>. If I make a mistake, I instantly get it pointed out by people like you, that know what they are doing. If I write something outstanding I get told that aswell, but not by simple "well done" one-liners, but by thought-out reflections, again, by people like you.</p>
<h2 id="the-future">The future<a href="#the-future">#</a></h2>
<p>Since it's vacation, I get the time to sit down and think about how I want things to develop here. And what I've come to realize is that I've underestimated the value of you and your feedback. What do I mean by that? Well, every damn comment (not spam, mind you), gives something back to me, something that I can use to write an even better article next time. I have not acknowledged that enough, that every comment is valuable to me.</p>
<p>Where Joel on Software thinks <a href="http://www.joelonsoftware.com/items/2007/07/20.html">comments infringe his freedom of expression</a>, I of course disagree. I find it utterly silly that they would.</p>
<p>Anyway. What it all boils down to, is that I need to make this site mirror my feelings about my readers… I'd like to move from a blog where I talk and you listen, to a platform where <strong>we</strong> talk. Of course that isn't an easy task. I can't force you to just "be more active". I can't force you to help each other and post your "lessons learned" here. That's not how a community works, and it shouldn't be.</p>
<h2 id="moving-to-a-community">Moving to a community<a href="#moving-to-a-community">#</a></h2>
<p>What I want to do is make it easy and convenient to interact with the site. To lift everything you do and write and show it to everyone. I know there's about 1000 people subscribing to my feed (about 300 daily visitors). Let's say one tenth of those, 100 loyal subscribers, are people really read what is posted and are willing to give feedback on some of it. Wouldn't that be a good crowd to show <strong>your</strong> ideas to?</p>
<p>I'm not saying I would post less, and expect you to fill the blanks. No, I would still post as much as I do right now, one article every other week. I would still read every comment. But I think there should be a way for you to start topics/articles and ask questions. And not only talk to boring me, to the other loyal 100.</p>
<p>The important question here is: <strong>Is this something you want?</strong> Would Friendly Bit still be as exciting if it was a community instead of a blog? Would you stay?</p>
<p>Mind you, I will read every single reply to this post carefully, and decide where to go from here. Thanks!</p>
What italic means2007-07-05T07:25:09+02:002007-07-05T07:25:09+02:00http://friendlybit.com/html/what-italic-means/Emil StenströmFinally an image that dispells all myths about the <i> element. As you can see it's all about presentation. Disappear you foul demon! (You have more HTML...
<p><a href="/files/post-media/i-sarah.jpg" data-no-instant><img src="/files/post-media/i-sarah.jpg" alt="HTML Humour: Italic cat" width="100%" /></a></p>
<p>Finally an image that dispells all myths about the <code><i></code> element. As you can see it's all about presentation. Disappear you foul demon!</p>
<p>(You have more HTML humor? Show me in the comments)</p>
Quick Accessibility Testing2007-06-24T21:57:53+02:002007-06-24T21:57:53+02:00http://friendlybit.com/tutorial/quick-accessibility-testing/Emil StenströmA recent project of mine required me to do a quick review of the accessibility level of a site. Nothing serious, just to show what was possible to test and...
<p>A recent project of mine required me to do a quick review of the accessibility level of a site. Nothing serious, just to show what was possible to test and where the site scored right now. I managed to assemble a small list of tools that I believe did a rather good job. This article is a list of those tools, and some tips on how to use them.</p>
<p>First off, to do a real accessibility test, you need real people, with real tasks to accomplish. These are not tools to replace people. Instead, they can give you a quick rundown on where you stand, and find things you've missed. I like to compare it with HTML validation: Validation is a great way to find your errors, but just because you validate does not mean you have good code.</p>
<p>Oh, by the way, I limited this to only free tools. Thought you'd like that. Also, for your enjoyment, I've split this article into three parts (you're just soooo spoiled):</p>
<ul>
<li><a href="#auto">Automatic testing</a></li>
<li><a href="#semi">Semi-automatic testing</a></li>
<li><a href="#manual">Manual testing</a></li>
</ul>
<h2 id="auto">Automatic testing<a href="#auto">#</a></h2>
<p>Automatic testing is one of the quickest way you can check your site's accessibility. What the authors of the below tools have done is to go through the available standards, and tried to find things that a computer can check. The tools will not find every error, but the things they do find, they find quickly. This is why I like to start with these.</p>
<ul>
<li><strong><a href="http://validator.w3.org/">W3C Markup Validation Service</a></strong> - This is a real classic. It goes through your HTML or XHTML and makes sure you follow the basic syntactic rules. What does this have to do with accessibility? Well, if you deliver invalid code, you have no chance but to test every user agent and how it renders your page. Will you do that? Didn't think so.<ul>
<li><strong>Bonus #1</strong>: Test up to 100 pages of your site at once with the <a href="http://htmlhelp.com/tools/validator/">WDG HTML Validator</a>, just check "Validate entire site" before you validate.</li>
<li><strong>Bonus #2</strong>: As a developer it's handy to get to know directly if the page you're looking at validates or not. <a href="http://users.skynet.be/mgueury/mozilla/">HTML Validator for Firefox</a> is an extension that sits in your browser's status bar, and shows a red cross when something is wrong. When you double click the icon it shows you the exact error. Very handy.</li>
</ul>
</li>
<li><strong><a href="http://jigsaw.w3.org/css-validator/">W3C CSS Validation Service</a></strong> - Even though screen readers don't care much about the CSS you need to make sure it's alright. Why? Because there's more to accessibility than screen readers. Surely, most people that need your help are people surfing with their ordinary browsers: Internet Explorer, Firefox, and so on. To make sure all of them see the content and can interact with it, check your CSS for obvious errors automatically.</li>
<li><strong><a href="http://www.cynthiasays.com/">Cynthia Says</a></strong>, <strong>WebXACT</strong>, and <strong>Wave Accessibility Tool</strong> are all testing tools that are aimed at accessibility testing. They support both Section 508 (an American accessibility standard) and WCAG 1.0 (W3C's own standard). Like the W3C tools above they do not catch all errors, in fact, most of the feedback you get is that you should check things manually. None the less, they often find simple errors that you have missed. Make sure you enable all extra options when using them.</li>
<li><strong>Basic accessibility analyzer</strong> is a much less known, but very impressive accessibility tester. Among other things it adds checks for proper heading structure and form labels, two things many have problems getting right. Built by Peter Krantz (former colleague of mine) and based on his <a href="http://www.peterkrantz.com/raakt/wiki/">accessibility library</a> for Ruby).</li>
<li><strong><a href="http://validator.w3.org/checklink">W3C Link Checker</a></strong> is another tool that's easy to forget about. It walks through your site and picks out all the links it finds, checking that each of them works. Using a tool like this makes sense for more than accessibility reasons, but accessibility alone is a reason to use it.</li>
<li><strong><a href="http://juicystudio.com/services.php#hosted">Juicy Studio</a></strong> hosts a whole series of useful online automatic tools. There's tests for Readability, Your CSS file, Luminosity and Color Contrast (really useful), and an Image tester. You will most certainly find something to improve here.</li>
<li><strong><a href="http://nikitathespider.com/">Nikita the spider</a></strong> is a great tool going through a lot of pages in search for errors. It crawls through a site and reports broken links, missing doctypes, and validation errors. Good for big batch checks after the fact.</li>
</ul>
<h2 id="semi">Semi-automatic testing<a href="#semi">#</a></h2>
<p>Semi-automatic tools do part of the work for you but also requires that you twiddle with the results yourself. They can't give you a "passed validation" stamp to put on your site, but correctly used they can give you deeper knowledge than the automatic ones.</p>
<ul>
<li><strong><a href="http://www.visionaustralia.org.au/ais/toolbar/">Accessibility Toolbar</a></strong> for Internet Explorer is a collection of accessibility tools bundled as a toolbar. The best part of it is it's support for color and contrast testing. Click "Colour -> Contrast Analyzer [application]". By selecting "Simulation" from the menu you can see what your site looks like with different vision impairments. If you rely on color alone for some feature it will be obvious with some testing with this tool.</li>
<li><strong><a href="http://www.standards-schmandards.com/projects/fangs">Fangs</a></strong> is a screen reader simulator in the form of a Firefox plugin. It's simply shows (not reads) the text on a page as it would be read by a screen reader. This is a great way to get a feel of how your site works with non-visual browsers. Due to a bug in Firefox you need to run an English version of the browser before installing Fangs. It's worth switching language to run Fangs, it helps that much.</li>
</ul>
<h2 id="manual">Manual testing<a href="#manual">#</a></h2>
<p>Then we have the old fashioned gruntwork, manual testing. I'm going to put things here that you don't use special tools for, just the browser and your accessibility knowledge.</p>
<ul>
<li><strong>Testing in several browsers</strong> is of course the most obvious way to test a site. If 10% of your users can't access the site because it doesn't work in Firefox you have a problem. So fire up both versions of Internet Explorer (6 and 7, not 5.5, it's dead), the latest version of Firefox and Opera. If you have access to a Mac make sure it works on Safari there too. If not you have to try with the buggy <a href="/other/safari-now-available-on-windows/">Safari 3 beta for Windows</a> (it's better than nothing).</li>
<li><strong>Text zoom</strong> is one of the first things you should try. Firefox and Internet Explorer 6 relies on only enlarging the text, and not the whole window, so make sure you test that. Internet Explorer refuses to zoom text set in pixels, so keep a lookout for that. Text zoom helped me greatly when my old monitor broke and got all blurry. Thanks for letting me zoom!</li>
<li><strong>Turning off CSS and Javascript</strong> is another great way to make sure people can access your content. You don't need to mind what the content <em>looks like</em>, just make sure it's understandable and that things work as expected.</li>
<li><strong>Remove images</strong> and replace them with alt text. There's options to do this with both <a href="http://chrispederick.com/work/web-developer/">Web Developer Toolbar</a> and the previously mentioned Accessibility Toolbar. Testing your image alternatives helps both people that gets their content read to them and those that disable image loading due to a slow dialup connection.</li>
<li><strong>Keyboard navigation</strong> is another thing to test. Just push your mouse to the side and navigate using only the keyboard (use the tab-key, arrows and enter). Does things work like you expect? Good, you passed.</li>
</ul>
<p>That's it. Lots of little tools and tricks you can use to make your site accessible to more people. If you ask <a href="http://www.useit.com/alertbox/">Jakob Nielsen</a> or <a href="http://www.456bereastreet.com/">Roger Johansson</a> if this is enough they will of course say no, but I say you should be proud anyway! Passing most of the above tests isn't easy, and you're certainly on the right track now. Well done!</p>
<p>Feel free to tip me off on more tools using the comments. Thanks for reading!</p>
Safari now available on Windows2007-06-11T20:08:28+02:002007-06-11T20:08:28+02:00http://friendlybit.com/other/safari-now-available-on-windows/Emil StenströmHi, this is just a short post to let you know that Safari is now available on windows. It's was unveiled at the World Wide Developer Conference 2007 by...
<p>Hi, this is just a short post to let you know that <a href="http://www.apple.com/safari/">Safari is now available on windows</a>. It's was unveiled at the <a href="http://developer.apple.com/wwdc/">World Wide Developer Conference 2007</a> by Steve jobs himself.</p>
<p>I can't stress enough how important this is for all Safari users. Most developers still use Windows when developing web sites (it's changing, but don't try to fool me, we're not there yet). Will all these developers test in Safari? Hell no, even though there's probably some hacky way to get Safari running, but I doubt many will go through the hassle of doing it. I know I don't. I also know that I now will test in Safari. For starters, this site is broken, need to fix.</p>
<p><strong>Congratulations all users of Safari</strong>, you have a bright future ahead of you. Also congratulations to Apple, for <a href="http://www.macrumorslive.com/">playing their cards exactly right</a> (first Intel Macs, now this).</p>
Min-width and Max-width template2007-05-28T20:57:31+02:002007-05-28T20:57:31+02:00http://friendlybit.com/css/min-width-and-max-width-template/Emil StenströmSome problems seem to appear again and again, and one of them is page width. How wide should a site be? Should you adapt to 800px resolution? 1024px? Fully...
<p>Some problems seem to appear again and again, and one of them is <strong>page width</strong>. How wide should a site be? Should you adapt to 800px resolution? 1024px? Fully fluid with percentages? Perhaps elastic using em-units? There are lots to choose from. What I've found is that there's one solution that almost always works. You most probably already know it, but I thought it might be helpful for some to have a template you just copy and use.</p>
<p>The idea is to use a fluid width but limit it by using <code>min-width</code> and <code>max-width</code>. As with almost all CSS tricks, we do a little bit of hacking for Internet Explorer 6 (IE6). Link to the working <a href="/files/min-max-template/" data-no-instant>min/max template</a> is available, and an explanation follows.</p>
<p>I'm picking 760px as the minimum width. It fits within a maximized browser window on 800×600 resolution, accounting for scrollbars. Next we need some kind of max-width, and for this I'm going to pick 960px. I could probably go a bit higher but 960 is nicely divisible with a lot of numbers, 3, 4, 5, 6, 8, 10, 12, 15, and 16, making for nice columns (see <a href="http://cameronmoll.com/archives/2006/12/gridding_the_960/">Gridding the 960</a>). Lastly we need some way to tell the browser to follow the width of the browser window when resizing, and width: 100% does that.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">wrapper</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">min-width</span><span class="p">:</span><span class="w"> </span><span class="mi">760</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">max-width</span><span class="p">:</span><span class="w"> </span><span class="mi">960</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>This assumes that you have a div with id wrapper around all your content.</p>
<p>The above works perfectly in both Firefox, IE7, Opera, and Safari. But (as usual) there's one culprit: IE6. To solve this I'm going to use the fact that IE allows for javascript execution inside CSS files. Have a look at the code below:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">wrapper</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">960</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="nf">expression</span><span class="p">(</span>
<span class="w"> </span><span class="err">(</span><span class="n">document</span><span class="err">.</span><span class="n">documentElement</span><span class="err">.</span><span class="n">clientWidth</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="mi">962</span><span class="p">)</span><span class="o">?</span><span class="w"> </span><span class="s2">"960px"</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="p">(</span><span class="n">document</span><span class="o">.</span><span class="n">documentElement</span><span class="o">.</span><span class="n">clientWidth</span><span class="w"> </span><span class="mi">762</span><span class="p">)</span><span class="o">?</span><span class="w"> </span><span class="s2">"760px"</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="s2">"auto"</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>First, the element gets a width by means of a IE expression(). The expression looks at the window width and if it's too wide it sets it to 960. It also limits it downwards to 760 pixels. At last we need to set trigger hasLayout on the element, and I usually use height: 1% for that (zoom: 1 works aswell).</p>
<blockquote>
<p><strong>Update</strong>: Martin suggests we add a default width when IE have javascript turned off. Excellent, added it to the example. The default width will be applied in IE if javascript is turned off.</p>
</blockquote>
<blockquote>
<p><strong>Update</strong>: Matthjis notes that there is a <a href="http://www.cameronmoll.com/archives/000892.html">bug in IE6</a> that causes it to freeze sometimes when using the same number for the conditional as for the max or min-value. Updated the code to reflect this.</p>
</blockquote>
<p>(The expression is built up with two tertiary operators, so <code>(condition)? "true value": "false value";</code>, with a couple of numbers in it. Check it, it makes sense.)</p>
<p>The IE6-stuff above will of course not validate (and doesn't work in other browsers), so what we do is enclose it inside a conditional comment. The final <a href="/files/min-max-template/" data-no-instant>min-/max-width example</a> has all the code you need (I've added centering too), but you should of course move the code to an external file.</p>
<p>Happy hacking!</p>
Don’t attach HTML-files in Outlook2007-05-28T21:42:01+02:002007-05-28T21:42:01+02:00http://friendlybit.com/html/dont-attach-html-files-in-outlook/Emil StenströmJust a short word of warning. I thought I'd mail the min-/max-width template to a colleague at work. So I fired up Outlook, attached the file and sent it. I...
<p>Just a short word of warning. I thought I'd mail the <a href="/files/min-max-template/" data-no-instant>min-/max-width template</a> to a colleague at work. So I fired up Outlook, attached the file and sent it. I thought that was it, Outlook couldn't get something simple like that wrong, could it? <strong>Yes it could!</strong> Opening the file I found some pretty nasty changes…</p>
<ol>
<li>A meta-tag with encoding gets added as the first line of the file (before the doctype). This naturally sends browsers into quirks-mode, effectively destroying most layouts.</li>
<li>Comments are removed from the file, including Internet Explorers own conditional comments. This makes sure any fixes you have applied gets removed, additionally destroying the layout in IE.</li>
<li>External stylsheets are instantly removed. You didn't think you could get away with that, did you?</li>
<li>Links get <code>onClick="return (false);"</code> added, making them not work.</li>
</ol>
<p>Have a look at the <a href="/files/min-max-template/index_mangled.html" data-no-instant>mangled Outlook file</a> (and the <a href="/files/min-max-template/" data-no-instant>original file</a>).</p>
<p>I'm sure there's more Outlook does, but those are the things that I noticed on this file. I've tried sending files and opening it with Thunderbird, and that seems to work, so the problem appears when you open the file from within Outlook, both when run as a native application and from the webmail version.</p>
<p>When sending off examples to your clients, do you know what e-mail client they use? Didn't think so. We better start zipping the files first…</p>
Spotify is a lot like…2007-05-08T20:46:02+02:002007-05-08T20:46:02+02:00http://friendlybit.com/other/spotify-is-a-lot-like/Emil StenströmHi. Today I want to tell you about a music player called Spotify, that I like. What does that have to do with web development? Nothing, that's why it's in...
<p>Hi. Today I want to tell you about a music player called <a href="http://www.spotify.com/">Spotify</a>, that I like. What does that have to do with web development? Nothing, that's why it's in the "other" category :)</p>
<p>Anyway. Spotify is a lot like <strong>Pandora</strong>, you know that music player that runs as a flash applet and suggests music based on your votes. Except Spotify comes as a standalone application, and doesn't suggest music. And it works outside of the US. Oh, wait, it's not at all like Pandora.</p>
<p>Instead, it's very similar to <strong>Last.fm</strong>, that massive music site that plays songs based on your tags, and suggests music if you pay for it. Well, except Spotify does not have tags, and it's free. Bah, it's not at all like Last.fm.</p>
<p>Oh, now I know, it's like having downloaded <strong>thousands of MP3s</strong> from some P2P network. MP3s you worked damn hard to find. But then again, music on Spotify is legal, and there's a lots more music there than what you will ever have on your hard drive. Damn it, it's not like downloaded music…</p>
<p>Aha! Now I know. It's like <strong>Winamp</strong>, but with a huge library of music, that you store on a remote server instead of on your own hard drive. A Winamp that can play and combine radio stations based on genres, filter out music from a certain century, and play full albums if you want to. A Winamp that's fully searchable on both artist, song title, and album, that displays CD covers, biographies and suggests similar artists. You guessed it right, it's not at all like Winamp.</p>
<p>Stay on the lookout for Spotify, soon released on an interweb near you.</p>
Vill du jobba med mig? (Swedish)2007-05-06T21:59:41+02:002007-05-06T21:59:41+02:00http://friendlybit.com/other/want-to-work-with-me-swedish/Emil StenströmSom ni säkert redan vet så jobbar jag som gränssnittsutvecklare på ett konsultbolag som heter Valtech i Stockholm, och just nu finns det jättemycket att...
<p>Som ni säkert redan vet så jobbar jag som gränssnittsutvecklare på ett konsultbolag som heter <a href="http://valtech.se/">Valtech</a> i Stockholm, och just nu finns det jättemycket att göra. Därför letar vi nu efter ytterligare någon som vill jobba med gränssnitt, och ta rollen som expert på HTML, CSS, Javascript, tillgänglighet, och allt annat som ingår i modern webb.</p>
<p>Det är en tjänst som konsult (på heltid), så det är ett varierande jobb, där du har stor möjlighet att anpassa vilka kunder du jobbar med. Valtech har kunder från alla möjliga branscher, men med fokus på stora företag, så möjligheten att påverka kvaliteten på den svenska webben är stor. Många kunder ber specifikt om webbplatser som följer "<a href="http://verva.se/web/t/Page____1154.aspx">Vägledningen 24-timmarswebben</a>", vilket gör en duktig gränssnittsutvecklares jobb enklare.</p>
<p>Du förstår säkert att jag stortrivs (jag skulle inte göra reklam här annars), men jag inser att en bloggpost inte är rätt medium för att förmedla det :)</p>
<p>Istället kan väl du, om du är nyfiken på tjänsten, <strong><a href="mailto:[email protected]">skicka ett mail</a></strong> till mig och berätta om dig själv. Vi ser helst att du har jobbat ett par år i branschen, men om du på annat sätt kan visa att du kan dina saker så är det ändå intressant.</p>
<p>Valtechs webbplats beskriver lite hur det är att jobba hos oss, och innehåller <a href="http://valtech.se/templates/Page.aspx?id=67">information om företaget</a>. Jag <a href="mailto:[email protected]">svarar gärna på frågor</a> om du skulle komma på några. Hoppas vi hörs!</p>
Reverse text with CSS (32 very special hex digits)2007-05-06T18:13:32+02:002007-05-06T18:13:32+02:00http://friendlybit.com/css/reverse-text-with-css-32-very-special-hex-digits/Emil StenströmSometimes you wake up and feel that big things are moving around you. You follow the news and find that people are uniting over something simple as a...
<p>Sometimes you wake up and feel that <a href="http://yro.slashdot.org/article.pl?sid=07/05/02/0235228">big things</a> are moving around you. You follow the news and find that people are uniting over something simple as a number. You read about people <a href="http://technology.timesonline.co.uk/tol/news/tech_and_web/article1749672.ece">calling them rebels</a>.</p>
<p>I think this is a good time to show a little CSS trick.</p>
<p>Let me present two properties that together reverse a string of text: direction and unicode-bidi:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">p</span> <span class="na">style</span><span class="o">=</span><span class="s">"direction: rtl; unicode-bidi: bidi-override;"</span><span class="p">></span>
0C 88 65 36 5C 65 14 8D B5 3E 47 D9 20 11 9F 90
<span class="p"></</span><span class="nt">p</span><span class="p">></span>
</pre></div>
<p>The result, when this is posted on your blog (*hint*) is the following:</p>
<code style="direction: rtl; unicode-bidi: bidi-override;">
0C 88 65 36 5C 65 14 8D B5 3E 47 D9 20 11 9F 90</code>
<p>Am I a CSS rebel now? And are they going to sue me on the basis of my HTML or my CSS?</p>
Transparent PNGs and IE6 standalone2007-04-28T20:44:31+02:002007-04-28T20:44:31+02:00http://friendlybit.com/css/transparent-pngs-and-ie6-standalone/Emil StenströmI'm one of many that have installed IE6 standalone and it really is a great solution to running both IE6 and IE7 on the same computer. Frequently people...
<p>I'm one of many that have installed <a href="http://tredosoft.com/Multiple_IE">IE6 standalone</a> and it really is a great solution to running both IE6 and IE7 on the same computer. Frequently people claim that IE6 standalone and the real IE6 render things differently but I've never seen that happen. Until now.</p>
<h2 id="why-an-alpha-transparent-image">Why an alpha transparent image?<a href="#why-an-alpha-transparent-image">#</a></h2>
<p>I'm working on a site with several alpha-transparent areas, where authors should be able to switch images and an semi-transparent box should cover half of that image. The users are not skilled enough with image programs to be able to add the transparent part to the image, and adding it to the image would prevent it from expanding when the containing text was zoomed. So I decided to use CSS together with alpha transparent PNGs to solve it. Let’s get to business.</p>
<h2 id="alpha-transparency-on-modern-browsers">Alpha transparency on modern browsers<a href="#alpha-transparency-on-modern-browsers">#</a></h2>
<p>Fireworks, my favourite image editor, allowed me to set the opacity to 60%. It smoothly exported my image to PNG and I positioned everything where it should be. Two background images later, one that the author could specify (added with a style tag in the head, <a href="/css/inline-css-should-not-be-allowed-in-strict-doctypes/">not with inline styles</a>), and one with the transparency. Everything worked flawlessly in Firefox, Opera, and IE7, as expected. Easy!</p>
<h2 id="ie6-and-alphaimageloader">IE6 and AlphaImageLoader<a href="#ie6-and-alphaimageloader">#</a></h2>
<p>IE6 does not support PNG images like that, so I decided to use what I always use to fix that, the <a href="http://support.microsoft.com/kb/294714">AlphaImageLoader Filter</a>. Note that the fix doesn't make the background specified with CSS work, it <em>adds a new</em> element to the page, on top of the element you apply it to. It's also proprietary, meaning it won't validate, so make sure add it to the page by using <a href="http://www.quirksmode.org/css/condcom.html">conditional comments</a>.</p>
<p>One thing you need to know to use the filter is how the <a href="http://msdn2.microsoft.com/en-us/library/ms532920.aspx">sizingMethod property</a> works:</p>
<blockquote>
<p><strong>crop</strong> - Clips the image to fit the dimensions of the object.</p>
</blockquote>
<blockquote>
<p><strong>image</strong> - Default. Enlarges or reduces the border of the object to fit the dimensions of the image.</p>
</blockquote>
<blockquote>
<p><strong>scale</strong> - Stretches or shrinks the image to fill the borders of the object.</p>
</blockquote>
<p>So there is no way to repeat an image as we're used to from CSS. Luckily, since I wanted a solid semi-transparent background repeating and scaling is the same, so I just did:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">breadcrumbs</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">filter</span><span class="p">:</span><span class="n">progid</span><span class="o">:</span><span class="n">DXImageTransform</span><span class="o">.</span><span class="n">Microsoft</span><span class="o">.</span><span class="nf">AlphaImageLoader</span><span class="p">(</span>
<span class="w"> </span><span class="n">src</span><span class="err">=</span><span class="s2">"semi_transparent.png"</span><span class="p">,</span><span class="w"> </span><span class="n">sizingMethod</span><span class="err">=</span><span class="s2">"scale"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<h2 id="making-links-work-in-ie6">Making links work in IE6<a href="#making-links-work-in-ie6">#</a></h2>
<p>You could think that we've hacked enough to get things up to speed with IE6, but no. Links on top of images loaded with filter does not work. The text of them are selectable, but you can't click them. Fortunately Ingo Chao fixed this in 2005 (some people are WAY ahead) by simply <a href="http://www.satzansatz.de/cssd/tmp/alphatransparency.html">adding an inner wrapper</a> with hasLayout enabled. Thanks Ingo!</p>
<p>Everything set, and tested in Firefox, Opera, IE7 and IE6 standalone. Phew!</p>
<h2 id="differences-between-ie6-standalone-and-ie6">Differences between IE6 standalone and IE6<a href="#differences-between-ie6-standalone-and-ie6">#</a></h2>
<p>After deploying the design on the client's server I quickly got a bug report back: "The breadcrumbs have a grey background, not a transparent one". I double checked the client's browser version to be IE6, and tested again locally on my own computer: it worked for me but not for the client. Confused I started looking for another computer with IE6 on (something that was surprisingly hard) I found one at the reception. Gotcha, the PNG was broken there too. I confirmed that IE7 was not installed and downgraded my own to IE6 again. Let's get to work!</p>
<p>After much fiddling with CSS I moved over to Fireworks again. It has three different versions of PNGs you can export as: PNG-8, PNG-24, and PNG32. I tried <strong>switching from PNG-24 to PNG-8</strong> and *blam* it worked!</p>
<p>I'm not sure why this works, but after reading the comments on the <a href="http://tredosoft.com/Multiple_IE">Multiple IE</a> page, I have a guess. To get filters to work in IE6 standalone two files are added to the IE6 folder. The authors picked them from an updated version of IE6; could it be that Microsoft updated the filters somewhere between my downgraded version and the latest IE6? After Googling I found an update to IE6 called SP1 which changes the behaviour of alphaimageloader. Quite likely, and very tricky to find.</p>
<p>Anyway, I hope this long story taught you something, I sure did it for me: Next time I'll use <a href="http://www.twinhelix.com/css/iepngfix/">Iepngfix.htc</a> instead :)</p>
IE7 Zoom Bug: Text width incorrectly calculated2007-04-28T17:44:03+02:002007-04-28T17:44:03+02:00http://friendlybit.com/css/ie7-zoom-bug/Emil StenströmIE7 shipped with a new and improved Page Zoom feature that lets you zoom more than just the text of the page. While I think I like it (there's many saying...
<p>IE7 shipped with a new and improved Page Zoom feature that lets you zoom more than just the text of the page. While I think I like it (there's many saying it will make developers lives easier), it has its bugs.</p>
<p>The most recent one I've seen is its failure to <a href="/files/ie7_zoom_bug/" data-no-instant>correctly calculate text width</a>. I've found no fix for this, except adding a right-margin, something that renders the box too wide instead of too narrow. The calculation seems to a little bit better with <code>font-style: italic;</code>, but it's still incorrect.</p>
<p>It you have a fix, let me know in the <a href="#comments">comments</a> (the usual stuff does not seem to work).</p>
<p>I guess the Page Zoom is hard to implement, since basic things like that breaks. At the other hand, Opera has had it for years, and Firefox will in version 3. I really look forward to explaining this to customers :)</p>
I’m not from America2007-04-17T21:25:08+02:002007-04-17T21:25:08+02:00http://friendlybit.com/other/im-not-from-america/Emil StenströmHi! Let me introduce myself. I'm a 25 year old web developer in Sweden. I use a 24 hour clock, which means I get up at 06.30 and go to bed at 23.00. I am in...
<p>Hi! Let me introduce myself. I'm a 25 year old web developer in Sweden. I use a 24 hour clock, which means I get up at 06.30 and go to bed at 23.00. I am in the timezone GMT+1, which probably means I get up when Americans sleep. To me, today is 2007-04-17, a Tuesday, the second day of my week.</p>
<p><em>Why am I telling you all this? Well, I'm getting tired of Americans assuming US is the world. When picking a random book from the bookshelf I'm expected to know how the educational system in the US works. I'm expected to know the names of popular persons in Hollywood. I'm expected to share your view of American gun policy, and I'm supposed to sing along to your national anthem.</em></p>
<p>When I shop things I use the Swedish krona (SEK), and I don't keep track of how it relates to other currencies, because I don't need to. Of everything I earn I pay about 30% in taxes to the government but got paid to study at the university (everyone here do). I'm writing this on a computer with a 100mbit connection, a fiber cable drawn to my apartment that I pay 229 SEK a month for.</p>
<p><em>There seems to be a problem in the US with coping with the rest of the world. I'm not disputing that America is where most of the money today is generated. If you say so. But I'm getting worried that Americans forget about the rest of the world.</em></p>
<p>Sweden has seven political parties, four of which rule the country right now. Two new parties got a lot of votes the last election but didn't get over the 4% barrier you need. The first one is the pirate party, working for integrity and loosened intellectual rights, and the second one is the feminist party, working for equality between the sexes. Each year there's new parties entering.</p>
<p><em>By not respecting and collaborating with the rest of the world you Americans are missing out on a lot of opportunities. What's worse is that since you brag about your excellence a lot of people envy you, but when you don't let them in your get them frustrated.</em></p>
<p>There's lots of people and countries in the world, <strong>don't assume I'm living in yours</strong>. Lets all hug.</p>
Convention about Web 2.0 coming up: hej! 20072007-03-30T19:19:00+02:002007-03-30T19:19:00+02:00http://friendlybit.com/other/convention-about-web-20-comming-up-hej-2007/Emil StenströmFor all the Swedish readers here: The 21:th of April there's a big convention coming up that I hope you don't miss. hej! 2007 takes on the wide and fuzzy...
<p><em>For all the Swedish readers here:</em></p>
<p>The 21:th of April there's a big convention coming up that I hope you don't miss. <strong>hej! 2007</strong> takes on the wide and fuzzy topic of Web 2.0 and presents speakers from a wide array of Swedish companies. I'll certainly be there and I hope you will too. Have a look at:</p>
<p><a href="http://www.nustart.sg/hej2007/">http://www.nustart.sg/hej2007/</a></p>
<p>See you there! (and let me know in the comments if you will attend)</p>
Currently moving2007-03-21T15:41:11+01:002007-03-21T15:41:11+01:00http://friendlybit.com/other/currently-moving/Emil StenströmJust a quick note to let you know that I'm currently in the process of moving. That means no internet for a couple of days. Stay tuned to the RSS, I'm not...
<p>Just a quick note to let you know that I'm currently in the process of moving. That means no internet for a couple of days. Stay tuned to the RSS, I'm not quitting :)</p>
What is Web 2.0? Really.2007-03-10T00:59:52+01:002007-03-10T00:59:52+01:00http://friendlybit.com/js/what-is-web-20-really/Emil StenströmWeb 2.0 is really hot right now. One of Sweden's biggest newspapers recently wrote a long article on their debate section. They had started linking back to...
<p>Web 2.0 is really hot right now. One of Sweden's biggest newspapers recently wrote a long article on their debate section. They had started linking back to blogs that linked to them, in a little box next to the article. The problem was that they had got into trouble with what blogs to link to. After all, you can't just link to anything, right?</p>
<p>Aside from starting to think about the implications of blog links, I got another interesting question in my head. What is Web 2.0 really? Most people working with interface development would say that Web 2.0 is everything that uses AJAX. But the newspaper didn't use AJAX at all, and still they claim links to blogs is Web 2.0. Time for some research!</p>
<h2 id="the-hunt-for-a-definition">The hunt for a definition<a href="#the-hunt-for-a-definition">#</a></h2>
<p>The phrase "Web 2.0" was first put into widespread use at an O'Reilly conference in 2004. The organizers wanted to talk about a change that has happened on the web, and just bumping the version of the web seemed like a good idea. Paul Graham found this <a href="http://www.paulgraham.com/web20.html#f1n">first try at defining Web 2.0</a> at the conference:</p>
<blockquote>
<p>"While the first wave of the Web was closely tied to the browser, the second wave extends applications across the web and enables a new generation of services and business opportunities."</p>
</blockquote>
<p>Note that there's no mention of AJAX there. Hell, there's no mention of users either! They must have meant something else, and the definition might have changed over the years since then. Let's keep looking for a good definition.</p>
<p>Tim O'Reilly comments on the issue two years later, in a <a href="http://radar.oreilly.com/archives/2006/12/web_20_compact.html">clarification on his blog</a>:</p>
<blockquote>
<p>Web 2.0 is the business revolution in the computer industry caused by the move to the internet as platform, and an attempt to understand the rules for success on that new platform. Chief among those rules is this: Build applications that harness network effects to get better the more people use them.</p>
</blockquote>
<p>Tim acknowledges the change in meaning and talks about "network effects" here, something that starts to look a little bit more like what my idea of Web 2.0 is. But isn't there still something missing? To me, that looks only like a small part of what I call Web 2.0. Let's keep looking…</p>
<p>Gartner has tried to convince companies of the merits of Web 2.0 for a rather long time. In one of their many (business oriented) PowerPoint presentations they attempt to define "three anchor points around Web 2.0":</p>
<blockquote>
<ul>
<li><strong>Technology and Architecture</strong> — Consisting of Web-oriented architecture (WOA) and Web platforms.</li>
<li><strong>Community</strong> — Looks at the dynamics around social networks and other personal content public/shared models, wiki and other collaborative content models.</li>
<li><strong>Business Model</strong> — Web service-enabled business models, mashup/remix applications and so forth.</li>
</ul>
</blockquote>
<p>I believe we're getting closer. Gartner is making business models a separate point which I don't agree with. Many of the biggest Web 2.0 sites didn't have a business model when they started (and many still don't). Digg has troubles covering their hosting cost with the tiny bit of money they acquire from their ads. Del.icio.us still doesn't make any direct money (although they got sold to Yahoo, and they surely use the data…). My point is, a business plan isn't one third of Web 2.0, it's something sites add afterwards if things work out.</p>
<p>So let me state my own (slightly more general) definition of Web 2.0:</p>
<blockquote>
<p>"A collection of ideas and techniques that can be used to make more interactive sites"</p>
</blockquote>
<p>The thing is, just doing something in AJAX does not mean it gets the Web 2.0 stamp of approval. You need several of the ideas or techniques and you need to combine them in clever ways. So lets agree on the definition above and got look for ideas.</p>
<h2 id="ideas-that-are-part-of-web-20">Ideas that are part of Web 2.0<a href="#ideas-that-are-part-of-web-20">#</a></h2>
<p>I'd like to gather a whole bunch of ideas under the Web 2.0 roof. My selection is of course not all there is. Googling could uncover more I'm sure, but I think this is a good start.</p>
<ul>
<li><a href="#generated">User generated content</a></li>
<li><a href="#trust">Radical trust</a></li>
<li><a href="#syndication">Syndication of content and services</a></li>
<li><a href="#tail">Long tail</a></li>
<li><a href="#collective">Collective intelligence</a></li>
</ul>
<h3 id="generated">User generated Content<a href="#generated">#</a></h3>
<p>Many companies still view the web as a one-way medium, an extension of a paper catalog, it's main advantage being that it can be distributed to more people. It's not like that any more! There are people that want to add content to your site, that want to contribute their ideas and thoughts. Why are you denying them to help you?</p>
<p>User generated content is content that your users are willing to give you. It can be everything from a simple "like it" or "don't like it", to fully featured articles written by users. The two most used ways of contributions are the simple ones: votes and comments. The author is still in full control of the content but users are given a chance to chip in with minor corrections. This is the least you can do. It's what I do on this blog; let you chip in by commenting.</p>
<p>But if you have users that are passionate about your subject, users that are willing to use your site to get their ideas out, you should really endorse that! Allow them to post articles on your site, allow them to regroup and re-prioritize according to their own wishes. It is technically possible, even rather easy to do; you just have to do it.</p>
<p>Six simple things your users can help you with:</p>
<ul>
<li>Reviews of your products</li>
<li>Comments on your articles</li>
<li>Stories about how people use your product</li>
<li>Multimedia using your product</li>
<li>Questions about your products</li>
<li>Articles in an area you choose</li>
</ul>
<h3 id="trust">Radical trust<a href="#trust">#</a></h3>
<p><img class="secondary" src="/files/web20/wikipedia.png" alt="Logotype of Wikipedia" /></p>
<p>Another approach many sites have taken can be summarized as "radical trust". It builds on the simple idea that users know what they want better than you do. So let them order, categorize, sort, select your data as they like!</p>
<p>This is exactly what wikis do. They acknowledge that there are more users doing good than doing bad. If that's the case, why not let them in on your content directly, letting them edit and improve it like they want. They few people that do bad can be hunted away with a combination with versioning (saving old versions of content that's easy to restore), and some simple monitoring. Wikis trust users, do you?</p>
<h3 id="syndication">Syndication of content and services<a href="#syndication">#</a></h3>
<p>Web 2.0 is not only about "user to website" interactivity. It's also about letting other sites and tools interact with your site directly. This is often summarized as "syndication".</p>
<p>It's a very fancy word for a simple concept. Let me try to explain.</p>
<p>Somewhere you have some kind of database with your content, be it products in your e-store or posts on your blog. Usually you take that content, add some structure (HTML) to it, and send it to the user.</p>
<p>Another website that wants to access the same information could parse the HTML and try to understand what it means, something called "screen scraping" (or microformats ;). The problem with that method is that it's very dependent on that the webmaster doesn't decide to change the HTML. The other problem is that computers and humans often want different types of information. A computer that is going to parse a list of your products doesn't need navigation like humans do. What you do is send your data directly to computers instead, without messing it up with HTML. Formats include: RDF, RSS, or perhaps custom XML through a Web Service.</p>
<p>Thing is, when you start syndicating your data you make it easier for others build services based on it. Now people get several entrances into your content instead of the one you produced. Again, your users are helping you reach more people.</p>
<p>Allowing full RSS feeds is another way of syndicating, I'm switching right now. Do you syndicate?</p>
<h3 id="tail">Long tail<a href="#tail">#</a></h3>
<p><img class="secondary" src="/files/web20/tail.png" alt="Graph of a sold units per item" /></p>
<p>The theory of the long tail is one of the ideas that are usually associated with Web 2.0. It's a business model that many companies that are successful on the web use. As with most business models they are invented after the fact, and as such I'm not sure it really belongs on this list, but people always bring it up, so let’s go. I'll let you choose yourself.</p>
<p>Wikipedia describes the long tail like this:</p>
<blockquote>
<p>"Products that are in low demand […] can collectively make up a market share that rivals or exceeds the relatively few current bestsellers and blockbusters, if the store or distribution channel is large enough"</p>
</blockquote>
<p>Most physical stores need to aim for the bestsellers to sell anything. There's simply too few interested in odd products, to make it worth hiring store space and personnel to sell it.</p>
<p>Web based stores are in a different position. Selling another product usually means just adding another page to your site, no extra store space or personnel needed. In addition people are prepared to wait a couple of days before receiving their products. That time span means you can skip warehouses and not start producing your products until you have an order ready.</p>
<p>No more is there a need to estimate what people will be interested in and pre-order them. For the right kind of product the internet is a huge benefit. Amazon did it with books, iTunes did it with music, do you do it?</p>
<h3 id="collective">Collective intelligence<a href="#collective">#</a></h3>
<p>You have let each user customize their experience and add content of their own. Now it's time to organize that content to better help the everyone benefit from it. There's hundreds of ways of doing it, but here's a couple of things that you can present to your users:</p>
<ul>
<li><strong>The most popular Swedish article right now…</strong> - Crawl all Swedish blogs and keep track of what they link to.</li>
<li><strong>Others that bought this book also bought…</strong> - Query your shipment table. Pick a product, select the number of times each other product appeared together with said product, and recommend that product to your customers. Amazon does this and it's said that it has increased their profits considerably.</li>
<li><strong>You probably think this movie is a four out of five</strong> - A Swedish movie site give its users personalized ratings of movies. They find users that have similar taste as you have (based on your previous grades) and then checks what those people have rated the movie as.</li>
<li><strong>This is probably spam</strong> - Write a word filter that learns what is considered spam when users mark them. Share that filter with fellow users and let their markings stop your spam. A form of collective sieve filtering, Akismet does this.</li>
</ul>
<p>None of them are technologically hard to do, you just Google and copy other people's samples. Why not?</p>
<h2 id="techniques-involved-in-web-20">Techniques involved in Web 2.0<a href="#techniques-involved-in-web-20">#</a></h2>
<p>But there are techniques involved too. Let's go through a few of the important ones.</p>
<ul>
<li><a href="#ajax">AJAX (and other javascript)</a></li>
<li><a href="#feeds">Feeds (RSS, Atom)</a></li>
<li><a href="#tags">Tags</a></li>
</ul>
<h3 id="ajax">AJAX (and other javascript)<a href="#ajax">#</a></h3>
<p>Everyone talks about AJAX together with Web 2.0, but I think it's important they are kept separate.</p>
<p>AJAX is just a technology that helps prevent (full) page reloads. Instead you connect to the server silently in the background and receive your data that way. What's the revolutionary about this technique? Nothing. It has been in use for at least 5 years. They new thing about it is that people started using it to build better interfaces.</p>
<p>Javascript is language that enables AJAX, and playing with reloads is not all it can do. Through some nifty use you can change attributes on any HTML element on the page. Move things around, react to mouse movement, fade and animate, it's your choice. This means a lot of new controls become possible, ranging from simple sliders to interactive maps.</p>
<p>Why do most accessibility people hate it? Because most developers don't know enough about accessibility. And when those start to use AJAX they disregard accessibility completely. Javascript and AJAX have different goals and I think a good compromise is making sure the basic functions of the site (buy a product and pay for it) works without javascript, but enabling it adds additional features.</p>
<p>When was the last time you used javascript to enhance your site? What was the last control you invented?</p>
<h3 id="feeds">Feeds (RSS, Atom)<a href="#feeds">#</a></h3>
<p><img class="secondary" src="/files/web20/feeds.png" alt="The official feed icon" /></p>
<p>Feeds are great for syndication of content. There are many different feed formats to choose from but they all have one purpose: to communicate pure data, skipping all design.</p>
<p>A feed is simply a list of feed items, each with an unique identifier. A user adds the address to their "feed reader" and it starts polling you, asking for updates. I have my reader set to just a couple of minutes, making sure I quickly notice changes in people's feeds.</p>
<p>The good thing about feeds is that they make it easy to follow several at once. There's no annoying different designs in the way if you don't want to (you can always just visit the site if you want design). Feeds are getting more and more of a commodity; you should already be allowing your users the possibility to subscribe your content. Do you?</p>
<h3 id="tags">Tags<a href="#tags">#</a></h3>
<p>Tags is another hip concept. It deals with the collective intelligence idea and how to categorize content efficiently. A tag consists of a phrase of some kind that describes a piece of content. This blog post could have the tag "javascript".</p>
<p>There's several ways you can use them. One is the just fix what tags are allowed and use them as regularly groups you can assign content to. But allowing more than one tag enable you to do more than just split things into groups, you can instead pick all contents bits that have the same tag. You can go further, allowing custom tags that the users can pick themselves. That gives you a wide array of descriptive words for your content, free to play around with. For example, if many users pick the same word, that one is probably a better descriptor.</p>
<p>Picking many bits of content and analyzing all tags tied to them can be easily done with a tag cloud. In that you simply print all tags used after each other, and make those used often bigger. Doing this on a whole site is an effective way of giving users a snapshot of what you write about, something I know I like.</p>
<p>Can tags help you solve a categorization problem you have?</p>
<h2 id="summary">Summary<a href="#summary">#</a></h2>
<p>Now. To build a Web 2.0 site, pick from both of the lists above. You Google for more ideas and you work hard to interact with your users as much as possible. Web 2.0 is the combination that happens when your ideas and technology finally just works.</p>
<p>Your users want to help you, do you let them in?</p>
Improving interactivity with Javascript2007-02-21T22:13:21+01:002007-02-21T22:13:21+01:00http://friendlybit.com/js/improving-interactivity-with-javascript/Emil StenströmPush buttons, radio buttons, check boxes, select boxes, and text inputs. That's the controls HTML allows us to use to interact with our users. A small...
<p>Push buttons, radio buttons, check boxes, select boxes, and text inputs. That's the controls HTML allows us to use to interact with our users.</p>
<p>A small dedicated group of people at the office (I work at <a href="http://www.valtech.se">Valtech</a>) sat down and listed all controls we could think of. The list below is basically that list, completed with examples where possible. Let me stress that the below controls are meant as <strong>inspiration</strong>. They are not all free, or even available for download. If you decide to use one of the ideas, google for them first and pick the best one. While selecting one, make sure it supports some kind of fallback for users without javascript enabled.</p>
<h2 id="slider">Slider<a href="#slider">#</a></h2>
<p>Slider control meant to let users select values from a range of options.</p>
<p><a href="http://webfx.eae.net/dhtml/slider/slider.html"><img src="/files/ajaxexamples/slider.png" alt="Slider control" /></a></p>
<h2 id="date-picker">Date picker<a href="#date-picker">#</a></h2>
<p>What format should this date be? What weekday is the 15:th of august? A good date picker helps the user answer those questions and makes filling in dates much more delighful.</p>
<p><a href="http://www.basicdatepicker.com/"><img src="/files/ajaxexamples/datepicker.png" alt="Date picker" /></a></p>
<h2 id="smart-text-boxes">Smart text boxes<a href="#smart-text-boxes">#</a></h2>
<p>It's easy to make some text boxes only allow certain kinds of characters. Why allow letters in the age field?</p>
<p><a href="http://www.cambiaresearch.com/c4/029c978b-aac5-472e-97a8-95b256f5febd/How-Can-I-Use-Javascript-to-Allow-Only-Numbers-to-Be-Entered-in-a-TextBox.aspx"><img src="/files/ajaxexamples/smarttextbox.png" alt="Text box that only allows numbers" /></a></p>
<h2 id="mixing-text-inputs-with-select-boxes">Mixing text inputs with select boxes<a href="#mixing-text-inputs-with-select-boxes">#</a></h2>
<p>Allow users to both input text and pick common options.</p>
<p><a href="http://www.google.com/webhp?complete=1&hl=en"><img src="/files/ajaxexamples/gsuggest.png" alt="Google Suggest" /></a></p>
<p><img src="/files/ajaxexamples/extratasty.png" alt="Ingredience picker with AJAX" /></p>
<h2 id="drag-and-drop">Drag and Drop<a href="#drag-and-drop">#</a></h2>
<p>Users are used to dragging and dropping things from their operating systems. Letting them do the same on the web makes for a great affect! Don't forget about a fallback though, not everyone uses a mouse (A buy-button is enough).</p>
<p><img src="/files/ajaxexamples/dragdrop.png" alt="Example shop with drag and drop" /></p>
<p><a href="http://www.panic.com/goods/"><img src="/files/ajaxexamples/panic.png" alt="Real shop with drag and drop" /></a></p>
<h2 id="collapse-and-expand-control">Collapse and expand control<a href="#collapse-and-expand-control">#</a></h2>
<p>Makes it possible to quickly show less important information on demand. Just make sure everything is open by default (with no javascript).</p>
<p><img src="/files/ajaxexamples/expand.png" alt="Toggling a block is easy" /></p>
<h2 id="advanced-tooltips">Advanced tooltips<a href="#advanced-tooltips">#</a></h2>
<p>When the title attribute is not enough. Use images, fine-tune the delay, make them sticky if you click them, it's all up to you!</p>
<p><img src="/files/ajaxexamples/tooltip.png" alt="Tool tips with a little spice" /></p>
<h2 id="autosaving-form-fields">Autosaving form fields<a href="#autosaving-form-fields">#</a></h2>
<p>If you write an email with <a href="http://www.gmail.com">Gmail</a> and the browser crashes, you'll appreciate that Gmail automatically saves your text regularly. It's done with a simple piece of javascript that periodically sends all your text off to the server, and saves it away. Simple and <strong>very</strong> useful.</p>
<h2 id="auto-validation">Auto validation<a href="#auto-validation">#</a></h2>
<p>While filling in some forms you'll notice a little green check on the side. I can't begin to praise how much faster this makes filling out forms. Directly after you've written enough letters in the password field you'll find that it's ok. No more trial and error against a slow server (unless you have javascript off, of course).</p>
<p><a href="http://www.zapatec.com/website/ajax/zpform/doc/demo.html#ajax.html"><img src="/files/ajaxexamples/autovalid.png" alt="Early notification that the password is correct" /></a></p>
<h2 id="controls-affecting-each-other">Controls affecting each other<a href="#controls-affecting-each-other">#</a></h2>
<p>In complex forms it's not unusual to want the user to fill in either one set of fields or another. The showing and hiding of what fields are available is a another perfect case of where javascript really helps.</p>
<h2 id="image-handling">Image handling<a href="#image-handling">#</a></h2>
<p>It's time to get easy handling of images in browsers. Javascript can help there too, by combining drag and drop with resizing and so on. Photoshop, here we come!</p>
<p><a href="http://www.walterzorn.com/dragdrop/dragdrop_e.htm"><img src="/files/ajaxexamples/images.png" alt="Images you can move and resize in the browser" /></a></p>
<h2 id="search-based-or-structured-navigation">Search-based or structured navigation<a href="#search-based-or-structured-navigation">#</a></h2>
<p>Sometimes new navigation schemes can be useful. Using search instead of navigation is an interesting idea. Another is letting the user pick categories and using them in search.</p>
<p><a href="http://www.vitvarumaklarna.se/"><img src="/files/ajaxexamples/searchstructure.png" alt="Menu that allows expanding and searching" /></a></p>
<h2 id="better-stronglookingstrong-form-fields">Better <strong>looking</strong> form fields<a href="#better-stronglookingstrong-form-fields">#</a></h2>
<p>Javascript also allows you to enhance existing form fields with prettier equivalents.</p>
<p><img src="/files/ajaxexamples/checkboxes.png" alt="Pretty form controls" /></p>
<h2 id="sortable-items">Sortable items<a href="#sortable-items">#</a></h2>
<p>Sometimes you want drag and drop in a more controllable manner. Why not use it to make it easier to sort your lists?</p>
<p><img src="/files/ajaxexamples/sortable.png" alt="Sortable list items" /></p>
<p>That's all! Hope I've given you some ideas of widgets/controls you can use to enhance user experience. Good luck!</p>
Tale of a lost mobile2007-02-07T21:09:05+01:002007-02-07T21:09:05+01:00http://friendlybit.com/other/tale-of-a-lost-mobile/Emil StenströmWhen I stepped off the bus today just outside of home I reached for my mobile phone. Eh? I checked all my pockets, every pocket in the rucksack I carry my...
<p>When I stepped off the bus today just outside of home I reached for my mobile phone. Eh? I checked all my pockets, every pocket in the rucksack I carry my laptop in, and went an extra lap around the bus station to see if I could find it. You all know the reaction after that: "FUCK!". Mumbling, I continued homeward. There was no chance I could intercept the bus or even know that the phone was there somewhere.</p>
<p>Finally at home I thought I'd call people and try to solve the problem, but the thing is that I have no other phone. The mobile is all, and it has worked fine until now. What to do, what to do? Well, I made sure that my internet connection worked out alright at least. It did.</p>
<p>Here's a little list of things I did, all thanks to the internet being available:</p>
<ol>
<li>Contacted a friend on IRC and made him call my number. Three rings later someone pressed "No" and didn't answer the call. What? Made my friend call again and he got directly forwarded to voice mail. Either someone turned it off or someone kicked it broken. Either way, it's gone forever.</li>
<li>Was able to contact one of my brother's friends on IRC. He told my that my brother say right next to him, so I could talk to him.</li>
<li>Made my brother call home and let my parents know that they might get (although not probable) a strange call sometime soon. Their number (conveniently named "A Homenumber") is the first one in my phone book.</li>
<li>Discussed with <a href="http://www.rundkvadrat.com">Björn</a> on ICQ about what to do and got the clever idea to block my sim card. I don't want people to be calling Korea with my money.</li>
<li>E-mailed Sara at the office, asking if she could help me with the block. Expected to fix it first thing in the morning. Left MSN addy at the bottom just in case.</li>
<li>Got contacted 30 min later on MSN by her (Note: this was way after working hours). She had called the support desk and fixed everything for me. Tomorrow I'll borrow an old phone, activate a new sim card, and have my old number working within an hour.</li>
</ol>
<p>So what do we learn from this?</p>
<ul>
<li>Well. Don't drop your mobile the day before you're about to buy your first flat. You risk losing the auction if you do stuff like that. DOH!</li>
<li>If you still manage to drop it, make sure you have someone like Sara that can help you fix everything 30 minutes after getting a casual e-mail. Check.</li>
<li>Make sure your company pays a new mobile every two years, and make sure you didn't buy one the last two years. <a href="http://www.valtech.se">Valtech</a> is nice. Check!</li>
<li>Back up your phone book to your computer. Back up? What's that? DOH!</li>
</ul>
<p><strong>Thanks everyone</strong> that helped me out! (and let me know if some of your friends proudly proclaim they found an <a href="http://www.sonyericsson.com/spg.jsp?cc=global&lc=en&ver=4001&template=pp1_1_1&zone=pp&lm=pp1&pid=10376">Ericsson W810i</a> on the bus.)</p>
<p><strong>Updated:</strong> Mobile found! I'm going to call someone named Monika tomorrow. Let's hope.</p>
<p><strong>Updated:</strong> Mobile found! Monika's daughter found the mobile on the floor on the bus I got home with. She called my parents and since she lived right next to them everything worked out all right. I got the phone back this morning, 10 hours after losing it. With a firm grip I then won the auction for a flat in Årsta. Yay, I have somewhere to live!</p>
Accessibility as a platform to build upon2007-02-03T14:00:23+01:002007-02-03T14:00:23+01:00http://friendlybit.com/html/accessibility-as-a-platform-to-build-upon/Emil StenströmTwo things triggered this post. First a brave participant at the last Geek Meet stood up and asked the question: "Why isn't it ok to require users have...
<p>Two things triggered this post. First a brave participant at the last <a href="http://www.robertnyman.com/geekmeet/">Geek Meet</a> stood up and asked the question: "Why isn't it ok to require users have javascript enabled?". A few days afterwards I got a lot of good replies to my article about <a href="/js/flash-only-vs-ajax-sites/">AJAX vs. Flash</a>, claiming that users want multimedia, not plain HTML. To me, those are two different ways of asking one fundamental question: "Is it time we start requiring more from our users?".</p>
<h2 id="html-our-history">HTML: Our history<a href="#html-our-history">#</a></h2>
<p>HTML has existed for (at least) 10 years now. The first browser, Mosaic, supported HTML and the same documents that where viewable then is still possible to look at in today's browsers. You know those polls that are still made to figure out the percentage of users that support javascript or flash? You don't need those for HTML, everyone supports it. Browsers, Mobile phones, Screen readers, Search engines… Everywhere you turn you have HTML support.</p>
<p>Now. HTML does not have everything you need to make a fully working website. So what you do is add another layer that figures out what the users what and generate HTML for them. It's an easy process and the point is that it does not put any pressure on the user at all, even today you can browse most sites with Mosaic. To me, that's fantastic! We truly have an global format for documents that works everywhere.</p>
<p>Semantic code and web standards did not change the basics, we still use the same header elements that where there from the beginning. What was added was a meaning to each element that had gotten lost in the table-era. Suddenly screen readers could just present a list of headers and know that they presented a balanced view of the site.</p>
<h2 id="but-we-want-more-than-that">But we want more than that!<a href="#but-we-want-more-than-that">#</a></h2>
<p>In parallell to semantic HTML, Flash and AJAX apps have evolved. They do a good job when it comes to interacting with the user, and interfaces instantly feel more alive. Some developers love them for that.</p>
<p>My thesis is that even though we do want more multimedia there's good and bad ways of getting it. Throwing away 10 years of accessibility can't be the best way? What I want is a way to have both a structured and readable site that is accessible from anywhere, <strong>and</strong> a site that can give users more interactivity if their browsers support it. Some say it isn't possible, but as a programmer I know that's not true. Based on previous comments I know it is possible to add a flash layer on top of a HTML site; you simply parse the HTML from flash.</p>
<p>You have probably figured this out already but this is what many AJAX apps are doing. They are adding a more interactive layer, on top of HTML. Done right that has incredible consequences for how applications can be accessed by all sorts of devices.</p>
<p><strong>Don't believe those who say accessibility rules out everything else. Use accessibility as a platform to build other apps on top of. Only require more for extras, not the basics.</strong></p>
Separation in the blink of an eye2007-01-23T10:10:11+01:002007-01-23T10:10:11+01:00http://friendlybit.com/css/separation-in-the-blink-of-an-eye/Emil StenströmI've seen them so many times: pages where the HTML is mighty fine (!) but the CSS looks like it's taken straight from Dreamweaver. While I hate having to...
<p>I've seen them so many times: pages where the HTML is mighty fine (!) but the CSS looks like it's taken straight from Dreamweaver. While I hate having to deal with those kinds of designs there is something good about them. They prove the point that HTML and CSS are two separate units, and that it's possible to mess up one of them and do fine on the other. That's after all the point of CSS…</p>
<p>Now. A much more unusual combination is good CSS together with bad HTML. So I put together a little example for you. <a href="/files/separation_illustrated/" data-no-instant>Separation illustrated</a> (only works in Firefox, I'm lazy). I've made all lines about 80 characters long and removed all other whitespace. Enjoy!</p>
<p>How's that for a company website?</p>
Flash-only vs. AJAX sites2007-01-16T00:02:35+01:002007-01-16T00:02:35+01:00http://friendlybit.com/js/flash-only-vs-ajax-sites/Emil StenströmEven though web developers like me have discouraged from building Flash-only sites for as long as I remember, they are popping up all over the place. For no...
<p>Even though web developers like me have discouraged from building Flash-only sites for as long as I remember, they are popping up all over the place. For no reason! We are ready to make the leap to standards. And our weapon with be AJAX.</p>
<h2 id="what-kind-of-sites-are-built-with-only-flash">What kind of sites are built with only Flash?<a href="#what-kind-of-sites-are-built-with-only-flash">#</a></h2>
<p>Let's start by having a look at a few big Flash sites. Because they exist, and keep popping up all over the place. Here's a couple of movie sites using it: <a href="http://thedeparted.warnerbros.com/">Departed</a>, <a href="http://www.sonypictures.com/homevideo/underworldevolution/index.html">Underworld Evolution</a>, <a href="http://whatisthematrix.warnerbros.com/">Matrix</a>; Here's a couple of big brands: <a href="http://www.coca-cola.se">Coca-cola</a>, Nike, <a href="http://electrolux.com/">Electrolux</a>. These sites are more than just animated images, they have their own content and often need to get updated continuously.</p>
<h2 id="whats-the-purpose-of-them">What's the purpose of them?<a href="#whats-the-purpose-of-them">#</a></h2>
<p>Before deciding on anything we need to examine what purpose these sites have. It's not OK to change the purpose of the site just because we dislike the technology behind it. I can't possibly know the reasons behind all of the campaigns going on today but I believe there's a core that most sites are after.</p>
<ul>
<li><strong>Promote something new</strong> - Someone wants to to push some of their products/deals/ideas to the spotlight.</li>
<li><strong>Specific target audience</strong> - Companies are well aware that what kind of people they reach initially will define if the product is successful or not. Many want the hip people.</li>
</ul>
<h2 id="updating-flash-files-is-hard">Updating flash files is hard<a href="#updating-flash-files-is-hard">#</a></h2>
<p>Many years ago it was ok just to throw up static information on a site and have a good site. Don't get me wrong, content is still king, what has changed is that content alone isn't enough. We demand much more from a good website. Coca Cola can't just publish a press release telling us that there is a new taste out. It's the Web 2.0 age and we want to be able to send our own tasting stories in, we want to be able to see live counters of the number of bottles sold, and we want forums to talk amongst ourselves about our experiences. We want tags! You get the point.</p>
<p>How does this affect the choice of flash or not? We need dynamics, ways for both editors and users to add content to the site, and <strong>Flash files are hard to update</strong>! Just the fact that I need a special program to edit them speaks for itself.</p>
<p>Another fact: As you probably know, it's rare (in the real world) to have the same person both writing code and publishing content. The coders need to cater for that, and make sure it's easy for editors to add new content. Now. Even if you've bought licenses and are able to edit flash files, you can't expect editors to understand all about how flash works. So you need to build a content management system (CMS) of some kind. If you buy one, you still need to integrate it with your current code.</p>
<p>"But", I hear you say, "…you have that same problem with non-Flash sites!". Yes, but the difference is that CMS tools that publish HTML have existed a lot longer. This affects both the quality, usability and ease of integration with current systems. A HTML-based site will therefore be easier to update, making for both more and fresher content that reaches more people. If it's easy enough to update the site, you can even let users do it, Web 2.0 style.</p>
<h2 id="flash-is-not-hip-any-longer">Flash is not hip any longer<a href="#flash-is-not-hip-any-longer">#</a></h2>
<p>Publishing a site with Flash today is hardly going to get mentioned at all. AJAX has completely taken over the scene and anyone even whispering AJAX gets to the front page of digg.</p>
<p>Aside from the technology buzz we have had some real changes rather recently: Javascript can now deliver what was once only available with Flash. It can fade, move, round corners, drag-drop, auto-save, validate, the list could go on forever… There's several effect libraries available that makes using all those effects easity. All the good ones are even free.</p>
<h2 id="flash-only-vs-ajax-the-showdown">Flash-only vs. AJAX - The showdown<a href="#flash-only-vs-ajax-the-showdown">#</a></h2>
<p>I've made a small list of things that matters when you build a website today, and evaluated each one of them for both Flash-only and AJAX.</p>
<table>
<tr>
<td>
</td>
<th scope="col">
Flash
</th>
<th scope="col">
AJAX
</th>
</tr>
<tr>
<th scope="row">
Accessibility
</th>
<td class="incorrect">
<strong>Poor</strong>. There's problems with everything from how a flash app gets its initial focus from the browser window, to unusual interaction controls, to lack of text resize. In summary, zero points.
</td>
<td class="almost">
<strong>Moderate</strong>. AJAX has problems with requiring js for accessing data, but smart developers have started thinking in terms of accessibility and fixed many of AJAX initial flaws. <a href="http://www.robertnyman.com/2006/02/08/ask-ajax-source-kit">Nyman's ASK</a> is one way.
</td>
</tr>
<tr>
<th scope="row">
Search Engine Optimization (SEO)
</th>
<td class="incorrect">
<strong>Poor</strong>. Search engines don't read flash files (even though they probably could). Some people claim that you should <a href="http://blog.deconcept.com/2006/03/13/modern-approach-flash-seo/">duplicate all your content</a>. I say that will be a mess to update.
</td>
<td class="almost">
<strong>Moderate</strong>. If you just use the javascript effects you are fine, if you fetch data with javascript you need to write a little script that reloads the content and gets it that way instead. It is possible, but not easy enough. Bonus: if you fix accessibility you often get this too.
</td>
</tr>
<tr>
<th scope="row">
Ease of content change
</th>
<td class="incorrect">
<strong>Poor</strong>. You need an expensive program to edit the files. ? Only available on PCs running Windows. Few CMS:es available (any?) that makes it easy for editors to update content.
</td>
<td class="correct">
<strong>Strong</strong>. All the big CMS:es can be used together with an AJAX app, it's just a matter of changing the templates on the front. Systems like Ruby on Rails (while not being a CMS) have built in support for AJAX stuff, but including a framework in older systems is no big deal.
</td>
</tr>
<tr>
<th scope="row">
Hipness
</th>
<td class="incorrect">
<strong>Poor</strong>. There used to be a big community of flash developers that got incredible respect in the webdev community with their flash-only sites. Many of these communities have been replaced by CSS Galleries of different kinds.
</td>
<td class="correct">
<strong>Strong</strong>. While Flash-only developers focused mainly on visuals the AJAX community have focused more on user experience, building applications that <em>feels</em> better to use. Together with the technology buzz behind it AJAX solutions have gotten (and still get) a great response from the start. The potential for marketing campaigns based on user experience in huge.
</td>
</tr>
<tr>
<th scope="row">
Graphic effects
</th>
<td class="correct">
<strong>Strong</strong>. This wouldn't be a fair comparison if we didn't acknowledge that Flash is far ahead of AJAX when it comes to graphic effects. Most of this is based in the fact that you are working in an application instead of a website, and things like anti-aliasing, drop shadows, transitions, and filters have existed for long.
</td>
<td class="almost">
<strong>Moderate</strong>. Websites was long lacking pretty interfaces but in the recent years we've seen an explosion of graphic effects even in the standards world, probably starting with the famous <a href="http://www.csszengarden.com/">CSS Zengarden</a>.
</td>
</tr>
<tr>
<th scope="row">
Integration with existing sites
</th>
<td class="almost">
<strong>Moderate</strong>. Few code libraries are written to work well together with flash, so often you have to do the integration yourself. In it's latest version Flash has gotten more integration points with the possibility to communicate with javascript, import HTML and so on. Better, but not perfect.
</td>
<td class="correct">
<strong>Strong</strong>. Most effect libraries are built to be as easy to include as possible. The usual way to make use of one is two lines long: link a javascript file and call the right function. The more advanced libraries that enable asynchronous loading require some more work, but unless you want advanced error handling it's no big deal.
</td>
</tr>
</table>
<p>Next time a customer ask for a Flash-only site, tell them about AJAX and it's advantages.</p>
Dear Justin Timberlake…2006-12-12T12:10:24+01:002006-12-12T12:10:24+01:00http://friendlybit.com/css/dear-justin-timberlake/Emil StenströmYou really are my big hero. When you swing your hips and slide over the floor so the ladies at the front row faint, I know I should have gone for superstar...
<p><img src="https://www.billboard.com/files/styles/article_main_image/public/media/justin-timberlake-vma-650d_0.jpg" alt="Justin Timberlake with scarf" class="secondary" /></p>
<p>You really are my big hero. When you swing your hips and slide over the floor so the ladies at the front row faint, I know I should have gone for superstar instead of web developer.</p>
<p>That Michael Jackson dance-alike thing you've got going really works; just look at your huge fan base, all eager to be like you. Paparazzi follow every step you make, eager to tell the world about all the little things you're up to.</p>
<p>This is why it surprises me that your website (<a href="http://www.justintimberlake.com">justintimberlake.com</a>) is using technology from 1996. How would it look if you walked around promoted something like the <a href="http://www.topspotz.com/blog/mullet.jpg">mullet haircut</a>?! Having a website like yours is just like that, you're promoting a technological mullet!</p>
<p>What's even worse, some of your fans are following suit and use the same ideas for their fan sites, with technology that blocks access for many users, that prevent search engines for finding them, and that adds extra work for them when updating.</p>
<p>So, how do we solve this problem of yours? Well, there's many options available. Let me tell you about my favorite:</p>
<p>Start by sneaking out of your fancy house. Make sure you avoid as many paparazzi as possible, but the idea is not to shake them all off. I'm sure you're much more skilled in these areas than I am. Now, meet me somewhere with a computer that has an internet connection. You probably want to send me a plane ticket: I'm guessing Stockholm, Sweden is a bit too far away from you.</p>
<p>Anyway, the idea is that I will teach you what I know about web development right there. You get a free course from a famous blogger (oh well, semi-famous in small parts of Sweden). The languages used are not hard to learn, don't worry about that, they are designed to be easy. You're a smart guy, so I'm sure it will go smooth. After the first day you will know all about structuring your site, after a week you'll be able to reconstruct your current site with modern technology. After that there's no limit.</p>
<p>When you've mastered web development we'll add a final twist. Accidentally, we'll reveal what you've been up to for the few paparazzi that are still following you. The headlines will be huge: "Justin Timberlake learns secret web arts" and "New way to grow your fan base: Justin explains". It will be great, and the media will go crazy! So, what do you think? Send me an e-mail at <a href="mailto:[email protected]">[email protected]</a> if you're interested.</p>
<p>Or, you could just hire someone good (ask for web standards and accessibility)… But what fun would that be?</p>
<p><strong>Update:</strong> Sorry Justin, I'm not gay, this is just about web development ;)</p>
Forgotten HTML elements?2006-12-04T19:59:26+01:002006-12-04T19:59:26+01:00http://friendlybit.com/html/forgotten-html-elements/Emil StenströmHTML has existed for a long time now with five released versions ([1], [2], [3.0], [3.2], [4.01]). Some very interesting elements have existed in previous...
<p>HTML has existed for a long time now with five released versions (<a href="http://www.w3.org/MarkUp/draft-ietf-iiir-html-01.txt" title="HTML 1 draft">[1]</a>, <a href="http://www.w3.org/MarkUp/html-spec/html-spec_toc.html" title="HTML 2 Specification">[2]</a>, <a href="http://www.w3.org/MarkUp/html3/Contents.html" title="HTML 3.0 Specification">[3.0]</a>, <a href="http://www.w3.org/TR/REC-html32" title="HTML 3.2 Specification">[3.2]</a>, <a href="http://www.w3.org/TR/html401/" title="HTML 4.01 Specification">[4.01]</a>). Some very interesting elements have existed in previous versions and I went on a little journey back in time to find and document them. Off we go.</p>
<p>Robert Nyman had a little contest a couple of weeks ago where he gave away an iPod to the person that <a href="http://www.robertnyman.com/2006/10/01/win-a-1-gb-ipod-shuffle-name-your-favorite-html-element/">best motivated why he/she liked a certain HTML element</a>. People gave a lot of good explanations and pretty much the whole HTML 4 specification was covered (even blink!). Knowing that all of HTML 4 was taken, and that he didn't specify what version of HTML to choose, I started searching through the older specs. I was soon stuck in HTML 3.0, and continued reading long after I had found my favorite…</p>
<p><code><note></code> was (and is) my favorite. <a href="http://www.w3.org/MarkUp/html3/notes.html" title="Specification of notes in HTML 3.0">Specified in HTML 3.0</a> as an element that's there for all kinds of little notes; a sidetrack to something you are currently speaking about, or perhaps some "operation failed" message. They even go as far as to recommend a few default class names: warning, notice, and error. Nice! Wouldn't this be nice in the current AJAX/Web 2.0 world where everything acts like an application? Why not use note for all those little messages? I could certainly see the use for something like that. Unlike me, the HTML 4 spec writers didn't see any use of such an element, and note was not included in HTML 4.</p>
<p><code><fn></code>, also <a href="http://www.w3.org/MarkUp/html3/footnotes.html" title="Specification of footnotes in HTML 3.0">from HTML 3.0</a>, is up next. Most of the "new" HTML 3.0 elements are aimed at different things that fit into the document metaphor, like research papers and books. So is the next one: fn is short for footnote, a name that clearly defines its purpose. It’s similar to the note element but meant for smaller notes. If you are trying to mimic a book, with references to somewhat disconnected information about something, this one is perfect. But why not use it for things like fancy tooltips while we're at it? Sadly, this element got kicked out of HTML 4.</p>
<p><code><isindex></code> is a bit different from the previous elements. It's defined as far back as <a href="http://www.w3.org/MarkUp/draft-ietf-iiir-html-01.txt" title="Specification of isindex in HTML 1">in HTML 1</a>, and was <a href="http://www.w3.org/MarkUp/html3/dochead.html" title="Specification of isindex in HTML 3.2">included</a> all the way to HTML 3.2. It was meant to represent that a certain page could be searched, but gave the user agent the option of how to get the query from the user. If put in the head of the document the user agent should prompt the user on load. If put in the body it should behave like one of those "search this page" form fields we are used to from Google.com. Needless to say, the exact same thing can be accomplished with a snippet of javascript or a HTML form. No need to let this one clutter the spec. Good removal.</p>
<p><code><banner></code> is another half-breed, <a href="http://www.w3.org/MarkUp/html3/banners.html" title="Specification of banner in HTML 3.0">specified in HTML 3.0</a>. It's meant for elements which should be set at a fixed position on the page, much like how position: fixed works in modern browsers. From the name you could think that this is an element you would want to block to get rid of ads, but the HTML 3.0 spec mentions that navigation inside the banner element is OK too. I believe the problem with this element is twofold: first, if it was meant for banners only, why should you want to put you advertisement inside it? That would just mean that it would be easier to block, and I'm sure most advertisers would dislike that. Second, if it's meant for "information that shouldn't be scrolled", then what's it doing in the HTML? That's certainly style, and should be in the CSS as well. Another good removal.</p>
<p><code><figure></code> actually has some uses (Also <a href="http://www.w3.org/MarkUp/html3/figures.html" title="Specification of figure in HTMl 3.0">from HTML 3.0</a>). It's meant for all types of media, and has built-in support for alternative content. It has ways to add image maps by using ordinary links and it has support for figure captions. Yes, this is a catch-all for any data that's not in text-format. Have a look at the <a href="http://www.w3.org/MarkUp/html3/figures.html">figure examples in the specification</a>, looks pretty nice doesn't it? Why was this removed? My guess is that the <code><object></code> element took its place (see <a href="http://www.w3.org/TR/html4/struct/objects.html#edef-OBJECT">object in HTML 4.01</a>). Object lets you specify more information about the "figures" its meant for, but does not limit itself to images. Yeah, there were reasons to remove figure from the spec too.</p>
<p>Well, that's all from friendly bit. Feel free to read through the specs in search for other elements that I've missed and post your findings in the comments. Perhaps <a href="http://www.whatwg.org/specs/web-apps/current-work/">HTML 5</a> will even revive some of the old elements?</p>
IE6 bug: Ignored selector hover bug2006-11-27T22:04:42+01:002006-11-27T22:04:42+01:00http://friendlybit.com/css/ie6-bug-ignored-selector-hover-bug/Emil StenströmIE6 bugs seem to pop up all over the place recently. This one is a very small one, but it might affect people that are building tabbed navigation or...
<p>IE6 bugs seem to pop up all over the place recently. This one is a very small one, but it might affect people that are building tabbed navigation or CSS-based tooltips. The problem is that IE6 ignores selectors in the form of <code>a:hover [selector]</code>.</p>
<h2 id="the-problem">The problem<a href="#the-problem">#</a></h2>
<p>Say you want to build a tabbed navigation where tabs move slightly when you hover them (that was how I found the bug). Since you want to reuse the images for the tabs you divide them into two pieces (according to <a href="http://alistapart.com/articles/slidingdoors/">sliding doors</a>). But to do that you need two elements that react on hover. One can be the link but you need one more. So you add a nested span and your code looks like this:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"url1"</span><span class="p">><</span><span class="nt">span</span><span class="p">></span>Home<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"url2"</span><span class="p">><</span><span class="nt">span</span><span class="p">></span>Contact<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"url3"</span><span class="p">><</span><span class="nt">span</span><span class="p">></span>About<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
</pre></div>
<p>You cleverly position the span and the link, and add a couple of rules to your stylesheet. You also want the text to move slightly, just like the background, so you add some padding.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">a</span><span class="p">:</span><span class="nd">hover</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="sx">...</span><span class="p">)</span><span class="w"> </span><span class="kc">no-repeat</span><span class="w"> </span><span class="kc">left</span><span class="w"> </span><span class="kc">top</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="w"> </span><span class="nt">span</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">block</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="p">:</span><span class="nd">hover</span><span class="w"> </span><span class="nt">span</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="sx">...</span><span class="p">)</span><span class="w"> </span><span class="kc">no-repeat</span><span class="w"> </span><span class="kc">right</span><span class="w"> </span><span class="kc">top</span><span class="p">;</span>
<span class="w"> </span><span class="k">padding-top</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>You look at the site in Firefox, Opera, Safari, and IE7 and everything works just fine. But what's that? Why doesn't the text move in IE6? You start removing CSS and HTML to pinpoint the problem and end up with a <a href="/files/ie6hoverpadding/" data-no-instant>very small testcase with the bug intact</a>.</p>
<h2 id="the-solution">The solution<a href="#the-solution">#</a></h2>
<p>Looking at the testcase I was just confused. I was pretty sure I'd seen IE6 do selectors like that before, but why didn't it work now? <a href="http://www.satzansatz.de/cssd/onhavinglayout.html">HasLayout</a> and the other usual IE6 fixes didn't work.</p>
<p>I loaded up my IM client and started asking people if they knew anything. <a href="http://simon.html5.org">Simon</a> noted that everything started working when you changed the selector to <span class="... "><code>a:hover, a:hover span</code></span>. Ok, so setting and then resetting that rule seemed to work. Some further experimenting revealed that just setting <strong>any</strong> padding to a:hover (setting it to zero worked well) also solved the problem.</p>
<p>That was good enough, an extra <span class="padding-top: 0 "><code>a:hover</code></span>. So here's the <a href="/files/ie6hoverpadding/fixed.html" data-no-instant>testcase with the bug solved</a>. The bug is apparently fixed in IE7.</p>
How to structure large CSS files2006-11-21T21:55:47+01:002006-11-21T21:55:47+01:00http://friendlybit.com/css/how-to-structure-large-css-files/Emil StenströmMany methods exist to structure your CSS. This article tries to describe the method I use. I call it the "Tree method", since it structures the CSS like…...
<p>Many methods exist to structure your CSS. This article tries to describe the method I use. I call it the "Tree method", since it structures the CSS like… that's right, a tree structure. I want to stress that it isn’t my invention; I just describe and give reasons for its rules.</p>
<p>Everyone that has built a bigger site has had to deal with the mess CSS so easily become. There are ids and classes all over the place, and to find where a certain class is defined you usually need to use some search feature in your editor. Matching the other way, from the CSS to the HTML is even harder; you don't even know <em>what file</em> a certain class is defined in. It’s a mess.</p>
<p>The Tree method tries to structure the CSS into logical blocks; blocks taken from the HTML. It also aims to be easy to understand for anyone. No secret codes or difficult ordering schemes.</p>
<ul>
<li><a href="#order">Order your selectors like the HTML</a></li>
<li><a href="#full">Always use the "full path" to elements</a></li>
<li><a href="#indent">Indent your code cleverly</a></li>
<li><a href="#own">Each declaration on its own line</a></li>
<li><a href="#alpha">… in alphabetic order</a></li>
</ul>
<h2 id="order">Order your selectors like the HTML<a href="#order">#</a></h2>
<p>One of the problems of mapping between the HTML and the CSS is that they usually differ in structure. The HTML is (if you’re lucky) structured like a convenient semantical tree while the CSS often is ordered by something random like fonts, colors, and positioning.</p>
<p>To make moving between the two worlds easier we want to make them as similar as possible. Is the HTML divided into header, content, and footer? Then make sure that's the three major parts of your CSS as well. Have you put the navigation above your header in the HTML? Then order it like that in the CSS as well! Any other structure makes moving from the HTML to the CSS much harder. You might be able to find all font manipulations in one part of the CSS, but only if you know that this particular developer uses that exact scheme. No, let’s keep it simple.</p>
<p>Here's a simple example where we just order the selectors:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="nt">h1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="nt">h2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="nt">p</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="nt">em</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="nt">strong</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>When grouping several styles into one definition I just put the group above both of their specific styles. <code>#header, #content</code> comes before both #header and #content.</p>
<h2 id="full">Always use the "full path" to elements<a href="#full">#</a></h2>
<p>The above is very easy to get an overview of, but the experienced developer knows that very few sites are that easy. Something you often want is a way to define different styles to different parts of a page. Let’s say you want green links in the navigation, but want to keep them blue everywhere else.</p>
<p>For this we use sub selectors. The selector <code>#navigation a</code> lets you give all links inside your navigation another look. But let’s take that further. Why not always write the <em>full path</em> to your elements? Why not use <code>#navigation ul li a</code> instead? Doing this gives a developer looking at your code a lot of information about how the HTML and CSS belongs together.</p>
<p>Lets add that to the previous example:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">h1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">h2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="nt">em</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="nt">strong</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>This does change the meaning from before. Before we selected all the level two headers; now we only select headers inside of the header division. Extending each selector with a "path" has made our CSS rules more specific, and specific means more control for you.</p>
<p>This also makes for fewer new ids and classes; just specify the path to an element instead of adding a class for it. Don't add a new class or id unless you really need to.</p>
<p>We still have the issue of "common styles"; styles that we want to apply to elements in different parts of the tree. Since they should be applied to all elements they don’t fit in the tree structure we've built. Instead we make a section in the beginning of the file (or a separate) with just "general styles". Don't add rules to this section if you only use them once in the document, you want as much of your code to be in "the tree" as possible.</p>
<h2 id="indent">Indent your code cleverly<a href="#indent">#</a></h2>
<p>To make the code even easier to understand I always add indentation (for those that don't know that word: it means spacing in front of blocks of text). Indenting makes the tree structure we're trying to build even clearer, you can easily find the major sections and dig down from there.</p>
<p>Lets add indention to you our example too:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">h1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">h2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="nt">em</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="nt">strong</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>Don't take indentation too far. If you're styling tables and using thead in the markup, but don't change the style of it, you can skip that indentation level. Double indention just for the sake of it is just a waste of space.</p>
<h2 id="special-case-templating">Special case: Templating<a href="#special-case-templating">#</a></h2>
<p>We also need to deal with rules that only appear on some of our pages. Perhaps we want the home page to look somewhat different than the sub pages? We solve this by giving an id or class to the body element. Doing this lets me specify styles for just one specific page, and setting the id or class on body makes me able to change anything in the document based on that.</p>
<p>These page specific styles need a place in the tree too. Here I tend to break from the above scheme and put them together with the style they change. So <code>body#page_home #header h1</code> is one step below <code>#header h1</code> in the tree. That makes it easier to see all styles for a certain element, instead of scrolling back and fourth (like you need to do if you don't remember your general styles). Keep your templates together with the style they change instead of completely separate.</p>
<p>If you want bigger changes, perhaps a totally different look on some pages, there's no reason to group things according to the scheme above. Move them to a separate file instead.</p>
<h2 id="own">Each declaration on its own line<a href="#own">#</a></h2>
<p>Indentation combined with full paths makes some lines rather long. This means that putting all declarations on one line will force you to scroll horizontally, something we already avoid on our sites. The simplest way to prevent horizontal scrolling is to use one declaration per line, so that's what the tree method uses.</p>
<h2 id="alpha">… in alphabetic order<a href="#alpha">#</a></h2>
<p>Grouping of properties is another issue. I've seen grouping schemes based on all sorts of things; from splitting things into "positioning", colors, and fonts, to people adding their properties completely randomly. I've chosen to just order them alphabetically. It's one of the few methods that bring some order while still being simple enough. I've seen total beginners do this by themselves; something I believe is a good argument for it. It's intuitive.</p>
<p>A simple example to illustrate:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="n">Blue</span><span class="p">;</span>
<span class="w"> </span><span class="k">font</span><span class="p">:</span><span class="w"> </span><span class="mf">3.4</span><span class="kt">em</span><span class="w"> </span><span class="n">Arial</span><span class="p">,</span><span class="w"> </span><span class="kc">sans-serif</span><span class="p">;</span>
<span class="w"> </span><span class="k">margin</span><span class="p">:</span><span class="w"> </span><span class="mf">0.5</span><span class="kt">em</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>One complaint I've heard on this method is that it splits up things that belong together. People tend to keep <code>position: absolute</code> and <code>left: 0</code> together, just to name one such pairing. It annoyed me at first too, but declaration blocks rarely contain more than 10 declarations, and the alphabetic order still makes them easy to find. Also, why handle position different than float and margin?</p>
<p> </p>
<p>That's it! By following a few simple rules you can get a CSS-file that's easier to overview, a file that you proudly can give away to the next developer. I can praise its existence all day, but you're the judge of whether it works or not. Why not give it a try in your next project?</p>
<blockquote>
<p><strong>Update</strong>: Maurice van Creij writes in and says that he's using the same method. A good way to get started is to generate a CSS file from the HTML. He has written a javascript that does just that. Nice! Try generating a CSS file.</p>
</blockquote>
<blockquote>
<p><strong>Update</strong>: Another part structuring your CSS is making sure you don't load too much. I wrote an article previously about <a href="/css/static-and-dynamic-css-combined/">combining static and dynamic CSS</a>.</p>
</blockquote>
<blockquote>
<p><strong>Update</strong>: This article got digged to the frontpage. There's a lot of good comments there (but as usual pretty harsh language).</p>
</blockquote>
Web development blogs you should read2006-11-19T04:40:48+01:002006-11-19T04:40:48+01:00http://friendlybit.com/css/web-development-blogs-you-should-read/Emil StenströmThe web is filled with blogs about web development. I'm always looking for good blogs to add to my feed reader and I thought some of you might do that too....
<p>The web is filled with blogs about web development. I'm always looking for good blogs to add to my feed reader and I thought some of you might do that too. So let me list the webdev blogs I subscribe to right now (in alphabetic order):</p>
<ul>
<li><strong><a href="http://www.456bereastreet.com/">456 Berea St</a></strong> - Roger Johansson is one of the most well known web developers out there, and it's for a reason. He posts almost daily about things happening in the webdev field. Everything from short comments with links to things to full blown articles.</li>
<li><strong><a href="http://headrush.typepad.com/creating_passionate_users/">Creating passionate users</a></strong> - Simply one of the best blogs there is, all categories. Deals with usability and making users happy. The posts are everything from hilarious to spectacular and I often get the motivation to write from here. Read an article or just look at one of the wonderful graphs. You'll love it.</li>
<li><strong><a href="http://www.thefutureoftheweb.com/">Future of the web</a></strong> - Jesse Skinner writes for all skill levels. Articles vary from basic markup to advanced javascript tutorials. Often with a twist of humour added in the middle of an article. Nice read.</li>
<li><strong><a href="http://mondaybynoon.com">Monday By Noon</a></strong> - Jon posts articles weekly (as reflected in the name) about all things related to web development. His friendly tone and ability to explain things makes this site ideal for people starting out. The good thing is that the same style works for more experienced people too. Try one of the articles, I'm sure you'll like it.</li>
<li><strong><a href="http://f6design.com/journal/">Pixel Acres</a></strong> - Jonathan Nicol combines webdev articles with thoughts on how to deal with clients and co-workers. Well written and qualitative, what else do you need?</li>
<li><strong><a href="http://www.robertnyman.com/">Robert's talk</a></strong> - Robert Nyman's blog, mixing personal posts with those that have to do with all kinds of interfaces. Entertaining read that feels balanced and well thought-out.</li>
<li><strong><a href="http://rundkvadrat.com/">Rund kvadrat</a></strong> - Blog in Swedish about making money on the web. While this isn't the primary concern for many interface developers we should certainly keep it in mind. Does moving a certain link upwards increase the client's sales?</li>
</ul>
<p>Well, and then there's all the big ones, but they tend to post too much about the conferences they attended and the books they wrote. Also, all their good articles end up on the big webdev news sites, which I also subscribe to.</p>
<p>Do you have any other sites that should be on that list?</p>
Web Standards Hero, episode 22006-11-07T22:18:47+01:002006-11-07T22:18:47+01:00http://friendlybit.com/html/web-standards-hero-episode-2/Emil StenströmRead episode 1 first The blistering cold hit him straight in the face as he left the warmth inside. Was it already this cold? He regretted not taking the...
<p><em>Read <a href="/html/web-standards-hero-episode-1/">episode 1</a> first</em></p>
<p>The blistering cold hit him straight in the face as he left the warmth inside. Was it already this cold? He regretted not taking the thick coat he had seen in the closet. The thin jacket he had right now had to do, there was no time turning back. It got a little better as he started jogging.</p>
<p>The table army had gotten quite a head start on him, but even at this distance he could hear their metallic legs marching forward, only interrupted by an occasional crash as they hit something in their way. No screams. Yet.</p>
<p>The town was rather empty on the winter season of the year, and the few permanent occupants had probably gotten to bed by now. A few years ago people would have gotten up from the terrible sound, but hardly any longer. Nightly fights between street gangs had made people afraid, and few would risk being seen.</p>
<p>Our hero increased his speed somewhat. He had an idea of how to get to the town hall before his opponents. The tables would probably keep to the main streets; if they took the smaller ones they might have to split up. They wouldn't risk that, few had any problems breaking a single table. So they would stick together on the bigger streets and he would stay on the smaller ones. He had the exact way plotted in his mind, and felt his speed increasing.</p>
<p>An elderly woman with her dog walked down a dark alley. She heard quick footsteps approaching from behind and quickly hid in the dark, covering the dog's mouth with her hand. From her hiding place she saw a young man with big yellow headphones approaching, he certainly looked to be in a rush; with determined steps and eyes fixed straight forward. He continued past her and she got ready to continue her walk. She threw one last look over the shoulder as to make sure she was safe. Like in slow motion she saw the young man being hit by something and flying through the air towards a brick wall. A screeching roar from a nearby alley convinced her not to linger. She quickly disappeared around the corner.</p>
<p>Our hero woke with his head against something hard. Touching his head he felt that the big headphones had taken the worst hit. The music continued from the other ear and for a while he just laid there listening to the deep base. When he thought about it, the base reminded him about something heavy moving its legs step by step: *Thump*, *thump*. *Thump*, *thump*. That's wasn't the base! He jumped out of the way as another spacer gif hit the ground where he had laid. In front of him was a gigantic black shape. A sign, swinging around its neck as it moved forward, clearly stated: "Made in Dreamweaver".</p>
<p>It really was huge, patched with layer over layer with machine-made material. Our hero doubted that his text-indent gun would be of any use. He knew he had to be smarter to outnumber this foe, but how?! As he nearly got hit by another gif attack as an idea struck him. He looked at the sewer drain, maybe 20 meters away, and started running towards it. He felt the creature behind him, too busy keeping up with him to be able to shoot anything. With a great leap, worthy of an athlete, he jumped over the drain and continued forward. After a few seconds he heard metal break as the creature stepped through the drain and disappeared down into the black water.</p>
<p>Yes! He stood still and tried to catch his breath for a while, and listened to the music flowing from only one side of his headphones. There was no doubt now, he was up against professor Font, the maniac who had killed his parents all those years ago. No one else could have created a monster like that. He felt an anger building up inside him and with eyes shining of feverish determination he continued towards the town hall.</p>
<p><em>Oh jolly gosh! What an adventure. Will our hero make it to the town hall in time? And where are those cookies you promised last episode?! Stay tuned for another episode of… Web Standards Hero!</em></p>
Feeds – a threat to design on the web2006-11-02T20:41:47+01:002006-11-02T20:41:47+01:00http://friendlybit.com/other/feeds-a-threat-to-design-on-the-web/Emil StenströmWhen CSS was first introduced it got bashed by a lot of sceptics. At least as many defended the language and in the end CSS was what got widespread use....
<p>When CSS was first introduced it got bashed by a lot of sceptics. At least as many defended the language and in the end CSS was what got widespread use. Today we see the exact same battle fought again, with feeds. Let me explain:</p>
<p>In the beginning HTML was a language for content exchange, and the content was mainly scientific papers. One thing you note about those papers is that all of them look the same. Sure, some use two columns and some use three, but very few were (or are) "branded". The widely accepted rule was to let the users decide the layout; after all why should we need to download the same design over and over? Design was something the user decided, not the author.</p>
<p>But those content-only sites didn't live long. First tables, then CSS, enabled users to make sites more interesting and in many cases easier to read. No one would come up with the idea or releasing an unstyled site today (except <a href="http://www.dustindiaz.com/naked-day/">CSS naked day</a> :).</p>
<p>Not too long ago feeds were introduced. Feeds make it easier to subscribe to websites by separating content from all the "design stuff". This enables users to decide how your content should look. Proponents often talk about how much faster it is to read content from different sites when they all look the same. No time is lost trying to understand a new design.</p>
<p>When you read the paragraph above you'll notice that it's the exact same discussion and arguments as were used when CSS was introduced: "Users should decide" vs. "Webmasters should decide". The difference between feeds and websites right now is that no one has gotten the idea of "designed" feeds. At least not yet, I believe we're slowly approaching that point. I read about someone switching to spans instead of strong because bold "didn't look right in the feed". Expect more of that.</p>
<p>Now. Since more and more people are moving towards using feed readers to access their favourite websites it's quite obvious that the tide is turning. One clear indicator is when people complain that sites don't have their full articles in their feed (known as partial feeds). But this is not just me defending my use of partial feeds: I believe we should take it further than that. What kind of web do we want? What kind of web do <strong>you</strong> want? Should we go back to an unstyled web where content is the only thing that matters? Did the "content only"-proponents win after all? Is it a "feeds only" web what we want?</p>
<p>I believe content on the web should be allowed to have a style, brand, identity; whatever you want to call it. Style is an essential part of web content and a skilled designer can enhance my whole web experience with little tricks I barely notice.</p>
<p>Long live design!</p>
Web Standards Hero, episode 12006-10-24T19:10:00+02:002006-10-24T19:10:00+02:00http://friendlybit.com/html/web-standards-hero-episode-1/Emil StenströmWith a long sigh he throws himself into the big leather sofa he invested in last summer. After a long day of angry customers bitching at him he really needs...
<p>With a long sigh he throws himself into the big leather sofa he invested in last summer. After a long day of angry customers bitching at him he really needs some rest. That idea to get a job at the local grocery store was not his best ever.</p>
<p>On the nearby foot rest a cup of warm chocolate spreads a little cloud of warm smoke. It's all nicely quiet, and he has had too few hours of sleep lately. Another big sigh and he feels his eyes slowly closing. The world turns blurry…</p>
<p>Out of nowhere a screeching sound breaks the silence! He's on his feet instantaneously and sees his warm chocolate make patterns in the air from his accidental kick. Damn it! The sound grows into something unbearably high-pitched and his hands unconsciously cover his ears. Where's that sound coming from? He pushes his body to move towards the sound, towards the big window against the street.</p>
<p>Stunned he looks at the procession before him: thousands of metallic tables march the street, drawing their wicked legs against the ground and crashing into everything around them. The sound is unbearable! With hands pushing harder against his ears he ponders: Do they marsh on their own? Highly unlikely, he quickly concludes: tables normally stay in the shadows and stick together to protect each other. The answer to his question is sitting at the top of one of the bigger ones: an old school webmaster swings his whip above him, pushing them forward.</p>
<p>This is serious. He takes a few steps backwards. The webmaster he saw was armed with at least 50 deadly spacer gifs, all ready to be thrown at anything that passes their way. Visualizing the town map he sees where they are heading, towards the town center. The public offices there are an easy target for them. He needs to act.</p>
<p>Temporarily letting the terrible sound reach his ears he quickly searches through a wardrobe for his old headphones. And there they are, huge like those ear defenders used by construction workers and bright yellow in color. He puts them on and welcomes the silence and the disguise. No one will recognize him with these on. He picks down a large wooden box from the top shelf. It has been several years since he last used it, but this calls for the heavy cavalry. He opens the lid and lifts up the big text-indent gun. A screw on the side adjusts it to 10000px, and attaches it to his belt after spinning it over his finger. This will get ugly.</p>
<p>Before leaving he stops at the door and picks up his mp3-player, plugging in the headphones and raising the volume. The electric beat steadily increases as he leaves he apartment with a clear goal in sight: to kick some serious table ass…</p>
<p><em>What will happen in the next episode of Web Standards Hero? Will our hero be able to stop the tables from reaching the town center? Will there be cookies? And what does professor Font have to do with all this? Stay tuned!</em></p>
<blockquote>
<p><strong>Update</strong>: <a href="/html/web-standards-hero-episode-2/">Episode 2</a> available</p>
</blockquote>
Click here to read this article2006-10-19T00:25:28+02:002006-10-19T00:25:28+02:00http://friendlybit.com/other/click-here-to-read-this-article/Emil StenströmNo matter where you go on the web today you see those little anonymous links: "click here)". You clearly see them, often marked with a different color...
<p>No matter where you go on the web today you see those little anonymous links: "<a href="#harmful-link">click here</a>)". You clearly see them, often marked with a different color (links as they are), but you don't immediately see where they go. Instead you need to read the text before, no wait, after, Oh! That's a nice image up there? Hmm… What was I looking for again?</p>
<p>It has been said over and over again; very few people actually read full articles unless they know it's worth it. It's all about trust. They must have previously gotten the idea that the article they are about to read is on topic, interesting, worth a read. It's a tricky situation, before they have read the article they need to somehow already know that they are on the right track. The solution is of course good links.</p>
<p>A link tells you something about the page you're about to visit. You get a quick two or three word summary, often from an author you have previously deemed trustworthy (after all, you're reading her/his site are you not?). When you are on a trusted site and click on a link you know that the destination is a good one. Why would there be a link there otherwise? You also know roughly what the site is about, it's summarized and underlined in blue right there. You click and you start reading.</p>
<p>Instead of the above scenario I see the same problem repeated over and over again. Instead of using good link text people use "click here" to name their links. You force me to read a lot more than I should need to. <strong>Damn you!</strong></p>
<p>But not only do you annoy your users. Search engines use link text as a primary source of information about the site linked to. Who wants to be found on Google only by those that search for "click here"? Sure, Google sometimes act like a persistent human and reads the surrounding text too, but it also values those words less. What? I can't use Google to find you? <strong>Damn you!</strong></p>
<p>Many screen readers have an option to only show the links for a site. This is a useful feature if you are browsing, navigating, searching for something, but know it's not on the current page. Since screen reader users are dependent on hearing things they navigate much slower than an average user and all ways of speeding up that process helps. On a page with the usual "click here" links, the generated list will be useless. The links are taken out of context and users are forced to read the whole site to see where a certain link goes. Why are you punishing them when it's so easy to do it the right way? <strong>Damn you!</strong></p>
<p>Sometimes the existence of “click here” links has to do with design. It's very popular right now to remove the underlining on links. This makes links harder to see and you need other methods to show the user where to click. One of them is telling the user what to do in text instead: "I want you to buy my product, but you can't by clicking directly, you need to click here". "Click me" designers: <strong>Damn you!</strong></p>
<p>And it's so easy.</p>
<blockquote>
<p>Link with the words that best describe the content you link to.</p>
</blockquote>
<p>Now. No one is going to do funny things with their comment signatures or trackbacks will they?</p>
IE6 bug: Encode and ignore2006-10-11T21:12:01+02:002006-10-11T21:12:01+02:00http://friendlybit.com/css/ie6-bug-encode-and-ignore/Emil StenströmI've previously talked about encodings and tried to explain how they work. This time I'll show you a bug in IE6 that is based on encoding problems. Because...
<p>I've previously talked about <a href="/other/character-encoding-basics">encodings</a> and tried to explain how they work. This time I'll show you a bug in IE6 that is based on encoding problems. Because if you don't watch out, IE6 might ignore whole rules in your stylesheet. If you want you can see the example right away: <a href="/files/encode-ignore/" data-no-instant>Ignore encoding example</a>. Open in in IE6 and compare with the rendering in a modern browser.</p>
<p>I've never seen this bug mentioned before so I took the liberty of naming it the <strong>"Encode and Ignore bug"</strong>. If you find it somewhere else, please tell, and I'll use that name instead.</p>
<p>Now. Stylesheets unfortunately have no way of specifying encoding. So you type away in your favourite text editor set to some obfuscate Greek charset and of course expect everything to work. It often does. CSS works with very few characters; mostly you just use the letters A-Z, some brackets, and colons. Since most charsets have those positioned similarly there's no problem. But there are exceptions where you want to use other letters too: inside comments and in the future: in generated content.</p>
<blockquote>
<p><strong>Update</strong>: <a href="http://rakaz.nl/">Niels Leenheer</a> points out that there are two ways to specify encoding on stylesheets. Either using the method in the <a href="/other/character-encoding-basics">encodings article</a> to send a proper HTTP header, or using the @charset "utf-8"; rule. The latter is just a rule you put on the first line of the CSS. Even seems to have decent browser support. Thanks Niels!</p>
</blockquote>
<p>So this Swedish friend of mine is learning CSS and I'm helping him out when he notices a strange error. When setting his html document to be encoded in utf-8 IE6 starts to display the page differently. I had never seen anything like it and start digging through the code. After like half an hour I find the culprit: an "å"-letter in a comment!</p>
<p>What he had done was add a comment after one of the colors he used, /* ljusblå */ ("light blue" in Swedish). When IE switches the HTML to UTF-8 the CSS seems to be switched with it. In UTF-8 mode the incorrectly encoded "å"-letter means something else, and IE not only ignores the comment or the line, but everything following it (still inside the current rule). So about half of a rule was ignored. I researched further and found that it was only triggered when the strange character was at the end of a comment.</p>
<p>Interesting, and easy to miss. The solution is of course to encode your CSS in the same charset as your HTML, or if you're lazy put some characters after the culprit. A very simple (and kinda rare) problem, but I thought it might save you an hour of debugging sometime.</p>
How web standards feels2006-10-11T21:34:42+02:002006-10-11T21:34:42+02:00http://friendlybit.com/css/how-web-standards-feels/Emil StenströmWhen talking about web standards many of us have started using marketing terms. Every day we hear about the bandwidth savings, the increased user base that...
<p>When talking about web standards many of us have started using marketing terms. Every day we hear about the bandwidth savings, the increased user base that are able to access your site, how well it affects SEO and so on. But none of that was what got me into all this. Let me tell you about the thing that convinced me: the feeling.</p>
<p>For me the web standards revolution started with a feeling that something was wrong. "There has got to be a better way", was a thought that buzzed in my ears when nesting my tables to create some padding.</p>
<p>I first saw CSS in other people's code, often embedded in style attributes with text-decoration: none; to remove underlines. I started experimenting, but the deeper aspects of how it could change the way websites were built didn't occur to me. It was just another tool to place things where I wanted them, and make things look like I wanted.</p>
<p>At that time I didn't know any server-side language so all my sites where frame based static HTML, often with a fancy javascript enabled select box for navigation. I did use some CSS just to remove the underlinings on my links, but that was it. Something still felt wrong, was this really the best way?</p>
<p>The "AHA!" feeling came much later; I'd love to say a certain moment when I understood but it wasn't a certain text or piece of advice, it grew on me. Suddenly everything felt like it had its place. It wasn't always obvious where that place was, but you could reason your way there. When the strength of CSS occurred to me, it was like finally understanding a tough mathematical formula. Yes!</p>
<p>So go ahead, show me your pretty charts of workday savings, <a href="http://csszengarden.com/">CSS Zen garden</a> remakes, or new techniques you can use. I like them, I really do, but I'm pretty convinced it's the "AHA!" feeling that finally wins people over to the web standards side.</p>
<p>What won you over? Can you convince someone else using that method?</p>
<p>(Inspiration from <a href="http://headrush.typepad.com/creating_passionate_users/2006/09/motivating_othe.html">Motivating others</a>)</p>
Character encoding basics2006-10-11T20:06:28+02:002006-10-11T20:06:28+02:00http://friendlybit.com/other/character-encoding-basics/Emil StenströmCharacter encodings is something that developers tend to push away as something too hard to bother with. It's not hard. It's just that there's several ways...
<p>Character encodings is something that developers tend to push away as something too hard to bother with. It's <strong>not</strong> hard. It's just that there's several ways of storing letters in a file. This article is my way of trying to explain how it works.</p>
<p>At first developers thought that 256 letters must be enough. Computers were for English speaking people only and few special characters where allowed. There were good reasons for this: memory was expensive and a fixed size for characters made the programming easier. This first way of storing things were called ASCII.</p>
<p>Time went by and people discovered that they needed letters that were not among the original 256. So what they did was replace a few special characters with the ones they needed. But different people needed different characters and soon we had hundreds of sets to select from. This mess is what you see if you select View -> (Character) encodings -> More (encodings) in your browser.</p>
<p>Encodings is just about mapping a certain number to the correct character. The first characters are often placed at similar spots, so your site does not necessarily break if you pick the wrong one. Very rarely do you need to know all of them. Just knowing that <strong>latin-1</strong> (sometimes called <strong>iso-8859-1</strong>) is the most popular one, but that there are better options out there, will get you far.</p>
<p>Having that many sets was clearly the wrong way to go, and smart people sat down together to come up with something better. They presented <strong>UTF-8</strong>, a way to store "all" possible characters in a single format. The idea is to save the first characters with just one letter, the next set with two numbers, three numbers, and so on. The exact <a href="http://en.wikipedia.org/wiki/UTF-8" title="technical details of UTF-8">technical details</a> does not matter, all you need to know is how it works in browsers and your favourite text editor.</p>
<h2 id="setting-the-right-encoding">Setting the right encoding<a href="#setting-the-right-encoding">#</a></h2>
<p>First you need to find out what encoding your HTML/CSS/JS editor produces. I highly recommend you to use UTF-8 if it's available, why be limited to just 256 letters? In my favourite editor right now, <a href="http://sourceforge.net/projects/notepad-plus/">Notepad++</a>, there's a "Format"-menu where I can select "UTF-8 without BOM". You probably have something similar in your settings.</p>
<p>When in UTF-8 mode you don't need to use HTML entities (those things that look like <code>&#345;</code>) that usually are used to produce strange characters. UTF-8 supports the character you need, just type it in, copy it from somewhere, or pick it from some list of available chars. If you use the correct charset selected everything will work alright. Good, you now have a file locally with some exotic characters in it (if not, you can use this string: "Iñtërnâtiônàlizætiøn").</p>
<p>In the browser world things works somewhat different. If the server sends a certain encoding, you can't do anything about it in your HTML. Many of you probably set the encoding using the meta element in HTML, something I find somewhat strange, how can the browser start reading the page at all if it doesn't know what encoding it's in? So, rely on your server to send the right encoding.</p>
<p>Start by checking what version your server sends by default: In the <a href="http://chrispederick.com/work/webdeveloper/">Web Developer Toolbar</a>, just go to the page you want to examine and select Information -> View Response headers. Look for Content-Type or Content-Encoding and se what it's set to.</p>
<p>If it's the wrong one (something other than iso-8859-1 and UTF-8 is probably wrong), you can change it like this:</p>
<p>Setting encoding to UTF-8 with <strong>PHP</strong>:</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="x">header('Content-Type: text/html; charset=utf-8');</span>
</pre></div>
<p>Setting encoding to UTF-8 with <strong>ASP</strong> and <strong>ASP.Net</strong>:</p>
<div class="highlight" data-language="ASPX-CS"><pre><span></span><span class="nt"><%</span><span class="n">Response</span><span class="p">.</span><span class="n">charset</span><span class="o">=</span><span class="s">"utf-8"</span><span class="nt">%></span>
</pre></div>
<p>Setting encoding to UTF-8 with <strong>JSP</strong>:</p>
<div class="highlight" data-language="JSP"><pre><span></span><span class="k"><%@</span><span class="w"> </span><span class="n">page</span><span class="w"> </span><span class="n">contentType</span><span class="o">=</span><span class="s">"text/html; charset=UTF-8"</span><span class="w"> </span><span class="k">%></span>
</pre></div>
<p>Setting encoding to UTF-8 with <strong>Java Servlets</strong>:</p>
<div class="highlight" data-language="JAVA"><pre><span></span><span class="n">resource</span><span class="p">.</span><span class="na">setContentType</span><span class="w"> </span><span class="p">(</span><span class="s">"text/html;charset=utf-8"</span><span class="p">);</span>
</pre></div>
<p>Setting encoding to UTF-8 with <strong>Python</strong>:</p>
<div class="highlight" data-language="PYTHON"><pre><span></span><span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s2">"Content-Type"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"text/html; charset=utf-8"</span>
</pre></div>
<p>Setting encoding to UTF-8 with <strong>Ruby on Rails</strong>:</p>
<div class="highlight" data-language="RUBY"><pre><span></span><span class="vi">@headers</span><span class="o">[</span><span class="s2">"Content-Type"</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"text/html; charset=utf-8"</span>
</pre></div>
<p>You probably have to include the snippet of code for the language you use in some template-file that's loaded before everything else. Test that everything works by reloading your sample page from your server and check the response with webdev toolbar.</p>
<p>Hope that helps someone!</p>
Judging the technical quality of a site2006-10-01T00:28:08+02:002006-10-01T00:28:08+02:00http://friendlybit.com/tutorial/judging-the-technical-quality-of-a-site/Emil StenströmWhen you look at a website to determine its quality on the code level, you need a different set of metrics than you did some years ago. This article is my...
<p>When you look at a website to determine its quality on the code level, you need a different set of metrics than you did some years ago. This article is my attempt at specifying what metrics I use. Have a look at them, do they match yours?</p>
<p>First I look at the <strong>validation</strong>. Does the front page validate? Do all sub pages of the site validate? If they don’t, what kind of errors are there? While validation isn’t the most important metric, it’s a very quick way to get a feeling of if the coder is “web standards aware” or not. I use the <a href="http://users.skynet.be/mgueury/mozilla/">Firefox validation plugin</a> that checks all the pages I visit and puts a little green check in the statusbar if the current page validates. For doing sitewide validation I use <a href="http://www.htmlhelp.com/tools/validator/">htmlhelp’s validation spider</a> and let it loose on the site (check "Validate entire site"). Validation is slowly catching on as a standard tool in the webdev toolbox. Someone who is not using the validator probably doesn't know much about web standards.</p>
<p>While on the subject of validation: don’t forget <strong>validating the CSS</strong>. There’s a lot of basic errors that the validator finds that only leads to errors in some browsers. The W3C CSS validator might help you fix some of those right away. Before you complain: the CSS validator has a few issues. If you use line-height, you need pass it a decimal number; 1 becomes 1.0, 0 becomes 0.0. Secondly, if you use CSS 2.1 or CSS 3 properties you need to inform the validator you do. Add the <a href="http://jigsaw.w3.org/css-validator/validator?uri=http%3A%2F%2Ffriendlybit.com&usermedium=all&profile=css21">URL parameter “profile”</a> with the value set to “css21” or “css3”, and revalidate. CSS errors and whether or not the style sheet is <strong>well organized</strong> clearly propagates what <a href="/css/levels-of-css-knowledge/">CSS level</a> the developer is on.</p>
<p>Next I look at the <strong>doctype</strong>. That single line of information at the first line of the HTML that defines what language the coder is using. Use of <a href="http://accessites.org/gbcms_xml/news_page.php?id=23">Strict or Transitional</a> is what matters most. Most pages that validate as transitional can with very small changes be upgraded to strict. And why not? Strict signals that an effort has been made to ensure that the document separates structure from design. If you know how, there’s no reason not to. At this stage I also check that the doctype is properly set, there’s an IE bug that makes IE render things badly (quirks mode) if the doctype isn’t the first element of the page. Incorrect use of doctype is also a common way to recognize a beginner.</p>
<p>Sites that pass the above code tests get another batch of checks. Is the code <strong>semantic</strong>? (ie. does the HTML describe the content?) I look at elements, classes, and ids in use. Do they describe the content they contain? Bad sites use class names tied to design. Mediocre sites use general names like “wrapper” or “column2”. Great sites use “copyright”, “invitation”, and “footnote”. Many CMS:es generate design-oriented classes and ids, and only a few reach mediocre. This is one way to see that a site was robot-made.</p>
<p>Another code issue is the <strong>content over HTML quotient</strong>. For just a few lines of content you shouldn’t have to need huge amounts of HTML. You shouldn’t need 10 divisions just for one header. A high content over HTML quotient signals that the developer knows what he’s doing. An “overmarked” site means that the developer is on the right track but suddenly forgot that content is more important than the code behind it.</p>
<p>One last angle is the <strong>accessibility</strong> one. How will a screen reader read this site? Is all the content of the site available as readable text? Does the site require javascript when it isn’t needed? A good place to see if someone knows about accessibility (on the web) or not is checking the forms. Fieldsets, legends, and labels: they all tell their story about the developer and his knowledge about accessibility.</p>
<p>A quality site ranks high in all of the above.</p>
Encyclopedia of HTML elements2006-09-20T23:53:36+02:002006-09-20T23:53:36+02:00http://friendlybit.com/html/encyclopedia-of-html-elements/Emil StenströmHTML is a much richer language than what it's used for. There are 77 elements and each one has a certain purpose. It is possible to find that reason by...
<p>HTML is a much richer language than what it's used for. There are 77 elements and each one has a certain purpose. It is possible to find that reason by reading the specification, but who does that? I wrote this list as a way to tell you what I think each of the HTML tags should be used for, common problems you might encounter, and general advise about each one.</p>
<p>I've included all the elements from HTML 4.01 <em>Strict</em>. It's a long one, but I'm sure you have more "tips and tricks" to add to it. Leave a comment and I'll add yours to the list too. Let's start off with a list of all the elements:</p>
<p class="linkblock">
<a href="#A">A</a>, <a href="#ABBR">ABBR</a>, <a href="#ACRONYM">ACRONYM</a>, <a href="#ADDRESS">ADDRESS</a>, <a href="#AREA">AREA</a>, <a href="#B">B</a>, <a href="#BASE">BASE</a>, <a href="#BDO">BDO</a>, <a href="#BIG">BIG</a>, <a href="#BLOCKQUOTE">BLOCKQUOTE</a>, <a href="#BODY">BODY</a>, <a href="#BR">BR</a>, <a href="#BUTTON">BUTTON</a>, <a href="#CAPTION">CAPTION</a>, <a href="#CITE">CITE</a>, <a href="#CODE">CODE</a>, <a href="#COL">COL</a>, <a href="#COLGROUP">COLGROUP</a>, <a href="#DD">DD</a>, <a href="#DEL">DEL</a>, <a href="#DFN">DFN</a>, <a href="#DIV">DIV</a>, <a href="#DL">DL</a>, <a href="#DT">DT</a>, <a href="#EM">EM</a>, <a href="#FIELDSET">FIELDSET</a>, <a href="#FORM">FORM</a>, <a href="#H1">H1</a>, <a href="#H1">H2</a>, <a href="#H1">H3</a>, <a href="#H1">H4</a>, <a href="#H1">H5</a>, <a href="#H1">H6</a>, <a href="#HEAD">HEAD</a>, <a href="#HR">HR</a>, <a href="#HTML">HTML</a>, <a href="#I"> I </a>, <a href="#IMG">IMG</a>, <a href="#INPUT">INPUT</a>, <a href="#INS">INS</a>, <a href="#KBD">KBD</a>, <a href="#LABEL">LABEL</a>, <a href="#LEGEND">LEGEND</a>, <a href="#LI">LI</a>, <a href="#LINK">LINK</a>, <a href="#MAP">MAP</a>, <a href="#META">META</a>, <a href="#NOSCRIPT">NOSCRIPT</a>, <a href="#OBJECT">OBJECT</a>, <a href="#OL">OL</a>, <a href="#OPTGROUP">OPTGROUP</a>, <a href="#OPTION">OPTION</a>, <a href="#P">P</a>, <a href="#PARAM">PARAM</a>, <a href="#PRE">PRE</a>, <a href="#QU">Q</a>, <a href="#SAMP">SAMP</a>, <a href="#SCRIPT">SCRIPT</a>, <a href="#SELECT">SELECT</a>, <a href="#SMALL">SMALL</a>, <a href="#SPAN">SPAN</a>, <a href="#STRONG">STRONG</a>, <a href="#STYLE">STYLE</a>, <a href="#SUB">SUB</a>, <a href="#SUB">SUP</a>, <a href="#TABLE">TABLE</a>, <a href="#TBODY">TBODY</a>, <a href="#TD">TD</a>, <a href="#TEXTAREA">TEXTAREA</a>, <a href="#TFOOT">TFOOT</a>, <a href="#TH">TH</a>, <a href="#THEAD">THEAD</a>, <a href="#TITLE">TITLE</a>, <a href="#TR">TR</a>, <a href="#TT">TT</a>, <a href="#UL">UL</a>, <a href="#VAR">VAR</a>
<p>For people that view this site in a visual browser I added colored bars on all the elements. They represent if an element is recommended to use or not. Green bar means "Use this!", Yellow means "Consider if you really need it", and Red means "Don't use this unless you have a really good reason".</p>
<h2 id="A" class="correct"><strong>A</strong> - Links, the very foundation of the web<a href="#A">#</a></h2>
<p>Should have the href attribute, but be sure to not include & in it. Write that as & instead.</p>
<p>Don't put blocks (<a href="#DIV">divisions</a>, <a href="#P">paragraphs</a>) inside of links or you will get a validation error.</p>
<p>If you set <code>display: block</code> on a link, you can set its width and height with CSS.</p>
<h2 id="ABBR" class="correct"><strong>ABBR</strong> - Explain what your abbreviations mean<a href="#ABBR">#</a></h2>
<p>Abbreviations are words which are short forms of a longer word or phrase. Examples include HTML, int, and Amex</p>
<p>Should have a title attribute with the explaination of your term.</p>
<p>Make sure this explanation is humanly readable (unlike how it's used in <a href="/html/current-issues-with-microformats/">microformats</a>). It's here to help <em>people</em> not machines.</p>
<h2 id="ACRONYM" class="almost"><strong>ACRONYM</strong> - Special case of the above where the word is formed from beginning parts of the words in a phrase<a href="#ACRONYM">#</a></h2>
<p>No need to use this one, abbr is enough. Do we really need to differ between acronyms and abbreviations? What about initialisms and the other types of words?</p>
<h2 id="ADDRESS" class="correct"><strong>ADDRESS</strong> - Contact information of some kind<a href="#ADDRESS">#</a></h2>
<p>Can be used for more than just street addresses, be creative! E-mail address and other contact info?</p>
<h2 id="AREA" class="almost"><strong>AREA</strong> - Define links in any shape<a href="#AREA">#</a></h2>
<p>Useful if you need clickable links in odd shapes. A possible example of this is a map with clickable regions.</p>
<p><a href="http://alistapart.com/articles/sprites#irregularshapes">CSS sprites</a> is another way of doing something similar using CSS.</p>
<p>Don't forget to specify alt text for your area links.</p>
<p>Isn't the shape of links really design? Should be specified in the CSS then, not in the HTML.</p>
<h2 id="B" class="incorrect"><strong>B</strong> - Make text look bold<a href="#B">#</a></h2>
<p>Don't use. Boldness is design and should be specified in the CSS using <code>font-weight: bold;</code></p>
<p>If you intended to show that something was very important you can use <code><strong></strong></code> instead. It describes the meaning better and has the same default styling.</p>
<h2 id="BASE" class="incorrect"><strong>BASE</strong> - Change your links to be relative to this address<a href="#BASE">#</a></h2>
<p>If you have to use this one, you're probably doing something wrong. I've seen terrible sites using this one.</p>
<p>There's a very strange <a href="http://www.456bereastreet.com/archive/200608/base_elements_cause_text_selection_problems_in_ie/">Internet Explorer bug with the base element</a></p>
<h2 id="BDO" class="almost"><strong>BDO</strong> - For foreign languages (ie. Hebrew), mark text direction<a href="#BDO">#</a></h2>
<p>This is a tricky one. I wouldn't say text direction is structure (and belong to the HTML), but it isn't design either (and belong in the CSS). Perhaps it's content?</p>
<p>Text direction can be set in the CSS with the <code>dir</code> attribute</p>
<h2 id="BIG" class="incorrect"><strong>BIG</strong> - set larger text relative to surrounding text<a href="#BIG">#</a></h2>
<p>Don't use. This is design and should be in the CSS. Use <code>font-size</code> instead.</p>
<h2 id="BLOCKQUOTE" class="correct"><strong>BLOCKQUOTE</strong> - Longer quotes<a href="#BLOCKQUOTE">#</a></h2>
<p>Include one or many paragraph(s) inside of this one.</p>
<p>Takes a cite attribute but this isn't rendered in browsers so use the cite <em>element</em> instead.</p>
<p>Don't ever use this one for indenting text, there's margin and padding in CSS for that.</p>
<h2 id="BODY" class="correct"><strong>BODY</strong> - All your real content goes inside this one<a href="#BODY">#</a></h2>
<p>Always use (even though a page without it for strange reasons still validate).</p>
<p>Never use bgcolor, background or the a-/v-/link attributes on body. Those can be set by using CSS instead.</p>
<p>Set a class or id to the body on each of your different pages if you want to style them differently. By using <code>body#contact div</code>, you can easily style all the divs on only the contact page.</p>
<h2 id="BR" class="almost"><strong>BR</strong> - Line break<a href="#BR">#</a></h2>
<p>Instead of marking the line-breaks between your items, mark the items! For ordinary text use <a href="#P">paragraphs</a> around each text block instead of breaks between them. Use a <a href="#UL">lists</a> and add a <a href="#LI">line item</a> around each of the items instead of separating them with line breaks.</p>
<p>A valid use-case is poems, where line breaks are part of poems themselves.</p>
<h2 id="BUTTON" class="correct"><strong>BUTTON</strong> - Alternative to inputs with types submit and reset<a href="#BUTTON">#</a></h2>
<p>A much more general way to add buttons to your form elements (Thanks <a href="http://pixelcarnage.net/">Rowan Lewis</a> for correcting my misstake.)</p>
<p>Allows you to add more than just text as the label, wrap the content you want inside of the button element.</p>
<h2 id="CAPTION" class="correct"><strong>CAPTION</strong> - Description of a table<a href="#CAPTION">#</a></h2>
<p>As many other <a href="#TABLE">table</a> elements, caption is sometimes hard to style with CSS in some browsers. If you start to get into trouble, use a header instead.</p>
<h2 id="CITE" class="correct"><strong>CITE</strong> - Source where quoted text originated<a href="#CITE">#</a></h2>
<p>Use together with <a href="#BLOCKQUOTE">blockquote</a> to connect the quotation and source.</p>
<p>Can be used to mark something as reference by wrapping cite around it. This could be useful if you are talking about a book but don't have a link to it.</p>
<h2 id="CODE" class="correct"><strong>CODE</strong> - Computer code example<a href="#CODE">#</a></h2>
<p>Perfect for authors writing about computer code.</p>
<p>Don't fall into the trap of using the lang attribute on code to specify what computer language your code is written in. The <a href="http://www.w3.org/TR/html4/struct/dirlang.html#h-8.1.1">specification clearly states</a> that's not allowed (I need to fix one of my plug-ins that does that on this blog). Thanks trovster.</p>
<h2 id="COL" class="correct"><strong>COL</strong> - Used to specify that some table cells belong together in columns<a href="#COL">#</a></h2>
<p>A very nice way of setting attributes of columns of cells in a table. Why not use this to set a class on that last column of cells you want to give that grey background?</p>
<p>Keep using <a href="#TH">table headers</a>, this is not a replacement for them</p>
<h2 id="COLGROUP" class="correct"><strong>COLGROUP</strong> - Shorter way of specifying table columns<a href="#COLGROUP">#</a></h2>
<p>Use colgroup instead of several col elements by setting the span attribute to the number of columns you want to affect.</p>
<h2 id="DD" class="correct"><strong>DD</strong> - Description of a term in a <a href="#DL">definition list</a><a href="#DD">#</a></h2>
<p>Several dd:s after each other means that there's many meanings to a certain term.</p>
<h2 id="DEL" class="almost"><strong>DEL</strong> - Mark deleted text in documents<a href="#DEL">#</a></h2>
<p>Good for marking up document revisions, where one author makes changes and what to clearly mark where.</p>
<p>An interesting idea is to use this for version management (together with <a href="#ins">ins</a>). Probably rare but an interesting idea. An example is how this is used at Wikipedia when comparing historical versions of an article (thanks Fredrico).</p>
<p>I have never seen an example where this element would be appropriate. Very rare.</p>
<p>Some screen readers are uncertain of what to do with the text inside of a del element. Should it be included in the page content or not? Be careful (Thanks <a href="http://www.standards-schmandards.com/">Peter Krantz</a>)</p>
<h2 id="DFN" class="correct"><strong>DFN</strong> - Term that's being explained by you<a href="#DFN">#</a></h2>
<p>Useful when you explain a term in the middle of a sentence. Add dfn around the word you explain.</p>
<p>A <a href="#DL">definition list</a> is more appropriate if you want to explain many terms at the same time.</p>
<h2 id="DIV" class="correct"><strong>DIV</strong> - Divider into logical parts<a href="#DIV">#</a></h2>
<p>Divide the page into logical parts. Typical examples are "header", "content", "sidebar" and "footer".</p>
<p>Divisions should only be used when there's no other better fitted element available. Keep the number of divs down as much as you can.</p>
<p>A similar element for inline stuff is the <a href="#SPAN">span element</a></p>
<h2 id="DL" class="correct"><strong>DL</strong> - List of definitions<a href="#DL">#</a></h2>
<p>Very useful for glossaries where you provide a term and it's explanation.</p>
<p>I use it much wider than just the above, more like a structure for matching key and value. Say you have a list of people and their preferred colors. I would use a definition for that.</p>
<p>Use dt for the key and dd for the value</p>
<h2 id="DT" class="correct"><strong>DT</strong> - What you define in a definition list<a href="#DT">#</a></h2>
<p>If you put two dt elements after each other that means that the two terms means the same. The explaination that follows applies to them both.</p>
<h2 id="EM" class="correct"><strong>EM</strong> - Important phrase<a href="#EM">#</a></h2>
<p>Use this to mark some part of your text a bit more important. Try not the think of the default styling, think importance.</p>
<p>If you want something stronger, use <a href="#STRONG">strong</a>.</p>
<p>It's not always possible to just change a italic element to a em element, are you really using it to mark up importance?</p>
<h2 id="FIELDSET" class="correct"><strong>FIELDSET</strong> - Groups form elements that belong together<a href="#FIELDSET">#</a></h2>
<p>Perfect if you have a first and last name in two different text fields and want to show that they belong together.</p>
<p>A <a href="#LEGEND">legend element</a> should be put inside of the fieldset to label it.</p>
<p>Fieldset borders are tricky with different browsers, I generally disable them with <code>border: none</code>.</p>
<p>Don't fall into the trap of using fieldsets for non-form elements. They are meant for grouping form elements, nothing else.</p>
<h2 id="FORM" class="correct"><strong>FORM</strong> - Wrapper for all kinds of form fields<a href="#FORM">#</a></h2>
<p>Use the form element just like you would use a <a href="#DIV">div</a>, like a wrapper.</p>
<p>If possible make sure your forms work without javascript enabled. I'm not asking that your sliding-fadeout-gradients are working, just make sure the basic stuff gets through.</p>
<h2 id="H1" class="correct"><strong>H1, H2, H3, H4, H5, H6</strong> - Headings for your sections<a href="#H1">#</a></h2>
<p>One of the most important elements in HTML. If you don't have any headers on a certain page you're most certainly doing something wrong. Think about your structure!</p>
<p>Always start with the h1 element. If you don't like the size, change it with <code>font-size</code>.</p>
<p>Don't skip levels of headings. If you have a h5 on the page, all four previous levels should be there too.</p>
<p>Different browsers have different default sizes for headings. Make sure you set the size for every one of them to get rid of that problem.</p>
<h2 id="HEAD" class="correct"><strong>HEAD</strong> - Container for meta data in the document<a href="#HEAD">#</a></h2>
<p>For validation, you only need a <a href="#TITLE">title</a> inside this element, but typical documents have a <a href="#LINK">link element</a> for the stylesheet, a <a href="#SCRIPT">script element</a> for the javascript, and some meta data inside <a href="#META">meta elements</a>.</p>
<h2 id="HR" class="incorrect"><strong>HR</strong> - Horizontal line<a href="#HR">#</a></h2>
<p>Don't use. This is design, the same effect can be accomplished through <code>border-bottom</code> in CSS.</p>
<p>Some people claim that hr is a section divider, but isn't that what we have <a href="#DIV">divisions</a> for?</p>
<h2 id="HTML" class="correct"><strong>HTML</strong> - Wrapper for everything except the doctype<a href="#HTML">#</a></h2>
<p>The HTML element can be used as a wrapper (an outer div around all content). Use this to get rid of one unnessesary wrapper.</p>
<p>Also takes the lang attribute that tells browsers what lanugage the site is written in (thanks <a href="http://sitesurgeon.co.uk/">Ben Millard</a>). This is extra useful for screen readers that needs to change their pronunciations. <a href="http://www.loc.gov/standards/iso639-2/langcodes.html">Language codes</a> are available through the US Library of congress. Use the two letter variants.</p>
<h2 id="I" class="incorrect"><strong>I</strong> - Italic text<a href="#I">#</a></h2>
<p>Don't use. Purely presentational way of adding italic styling. Use the <a href="#EM">em element</a> instead.</p>
<h2 id="IMG" class="correct"><strong>IMG</strong> - Embedded image<a href="#IMG">#</a></h2>
<p>Used incorrectly very frequently. IMG should only be used for images that can be considered content on the page. An example of this is a thumbnail gallery or a helpful image somehow connected to the text. Things that shouldn't be img elements are decorations: rounded corners, bullet points in lists, and page dividers. Use <code>background-image</code> in CSS for that instead.</p>
<p>If the image contains information that you want to convey, use the alt attribute to give that information to user-agents that doesn't load images.</p>
<h2 id="INPUT" class="correct"><strong>INPUT</strong> - Radio button, check box, text field, button, or hidden data<a href="#INPUT">#</a></h2>
<p>Element used as a building block for form fields. The type is determined by the setting the type attribute to either radio, checkbox, text, image, submit, reset, or hidden.</p>
<p>Other elements normally used together with this one is <a href="#SELECT">select</a> and <a href="#TEXTAREA">textarea</a>.</p>
<p>Make sure you add an id to each input field and tie an <a href="#LABEL">label element</a> to it. No input should be without it.</p>
<p>Wrap your inputs and labels in a <a href="#FIELDSET">fieldset</a>, paragraph or div to stop the validator from complaining that elements are not allowed where they are.</p>
<h2 id="INS" class="almost"><strong>INS</strong> - Inserted text<a href="#INS">#</a></h2>
<p>Similar to <a href="#DEL">del</a>, this element can be used to mark deleted text.</p>
<p>Might be useful for tracking changes in your document but again, I have never seen a site where this element was needed.</p>
<h2 id="KBD" class="correct"><strong>KBD</strong> - Text that should be entered on the keyboard<a href="#KBD">#</a></h2>
<p>One of the numerous elements that can be used to mark up documents about computers. Rarely used.</p>
<p>How do you know your user will use the keyboard?</p>
<h2 id="LABEL" class="correct"><strong>LABEL</strong> - Text that describes a corresponding form field<a href="#LABEL">#</a></h2>
<p>The for attribute associates this element with a form field id. Important out of an accessibility standpoint, both because it gives screen readers better info and because it makes form fields clickable (in most browsers, but not Safari, thanks <a href="http://www.456bereastreet.com/">Roger</a>).</p>
<h2 id="LEGEND" class="correct"><strong>LEGEND</strong> - Heading for a fieldset element<a href="#LEGEND">#</a></h2>
<p>Wrap this element inside each of your fieldsets to provide a reason why you think the following fields belong together. Typical examples include "Credit card", "Full address", and "Shipment details".</p>
<p>Somewhat tricky to style since browsers handle them very differently. I tend to keep them pretty plain.</p>
<h2 id="LI" class="correct"><strong>LI</strong> - Items in <a href="#OL" title="ordered list">ordered</a> or <a href="#UL">unordered lists</a><a href="#LI">#</a></h2>
<p>Gets different styling by default depending on browser: padding-left or margin-left. If you want to change the indention, make sure you first reset the other one.</p>
<h2 id="LINK" class="correct"><strong>LINK</strong> - A way to define links to other elements<a href="#LINK">#</a></h2>
<p>Most often used to define external stylesheets for the document (use <code>rel="stylesheet"</code>)…</p>
<p>.. but can be used to define <a href="http://www.subotnik.net/html/link.html.en">other types of relations</a> too. Some browsers show custom rel types to users like a list of bookmarks.</p>
<h2 id="MAP" class="almost"><strong>MAP</strong> - Wrapper for image map areas<a href="#MAP">#</a></h2>
<p>Used together with the <a href="#AREA">area element</a> for image maps.</p>
<h2 id="META" class="correct"><strong>META</strong> - Information about the document<a href="#META">#</a></h2>
<p>Can be used to for custom information about the document.</p>
<p>Search engines use some <a href="http://searchenginewatch.com/showPage.html?page=2167931" title="meta elements supported by search engines">predefined names</a> that you should know about.</p>
<h2 id="NOSCRIPT" class="incorrect"><strong>NOSCRIPT</strong> - Content to show if the browser doesn't support javascript<a href="#NOSCRIPT">#</a></h2>
<p>The default should be to show content that does not require javascript, we don't need a certain element for that.</p>
<h2 id="OBJECT" class="correct"><strong>OBJECT</strong> - Embedding other types of information in to document<a href="#OBJECT">#</a></h2>
<p>The new way of adding <a href="http://www.ambience.sk/flash-valid.htm">flash</a>, quicktime and other multimedia content to your site.</p>
<h2 id="OL" class="correct"><strong>OL</strong> - Ordered list of items<a href="#OL">#</a></h2>
<p>Ordering means that the content only makes sense in that order. This means that a step-by-step recipe is an ordered list, but a basic navigation menu is not (see <a href="#UL">unordered list</a>).</p>
<h2 id="OPTGROUP" class="correct"><strong>OPTGROUP</strong> - Group your option elements<a href="#OPTGROUP">#</a></h2>
<p>One of the least known elements in HTML. Impress your friends!</p>
<p>Similar to fieldset but for option elements. Wraps around them and uses the <em>label attribute</em> to name the group.</p>
<p>Nesting of optgroups is not allowed.</p>
<h2 id="OPTION" class="correct"><strong>OPTION</strong> - One of the choices in a select<a href="#OPTION">#</a></h2>
<p>If you set the value attribute, that value is sent instead of the text inside the element.</p>
<h2 id="P" class="correct"><strong>P</strong> - Wrapper around each of your paragraphs<a href="#P">#</a></h2>
<p>Replacement for line breaks (the br element).</p>
<p>By wrapping all your paragraphs in a p element you can easily change the space between them with margin or padding.</p>
<h2 id="PARAM" class="correct"><strong>PARAM</strong> - Set properties on embedded objects<a href="#PARAM">#</a></h2>
<p>The exact param names used depends on what you embed, check the documentation for the document you are dealing with.</p>
<h2 id="PRE" class="almost"><strong>PRE</strong> - Preformatted text<a href="#PRE">#</a></h2>
<p>Used to define that a certain piece of text is formatted (designed) in the HTML. While this is most often a bad idea there's applications in e.g. <a href="http://www.chris.com/ASCII/">ASCII art</a>, text-only e-mails, and Python code (thanks zcorpan).</p>
<p>Use <code>white-space: pre;</code> and <code>font-family: monospace;</code> to get the "pre design" with CSS.</p>
<h2 id="QU" class="almost"><strong>Q</strong> - Add quotations in a language independent way<a href="#QU">#</a></h2>
<p>Instead of setting what kind of quotes you use (there are several you know), you simply define that you're dealing with a quote and work out the details in a separate file.</p>
<p>Good idea, but no support by IE6 makes it a lot less useful.</p>
<h2 id="SAMP" class="almost"><strong>SAMP</strong> - Sample text or characters<a href="#SAMP">#</a></h2>
<p>Seriously, don't we have enough of the computer related elements already? If you need sample text that isn't code or keyboard type-in then fine, use this one.</p>
<h2 id="SCRIPT" class="correct"><strong>SCRIPT</strong> - Run javascript on your site<a href="#SCRIPT">#</a></h2>
<p>Remember to set the type attribute to text/javascript if that's what you use. Language is no longer needed.</p>
<h2 id="SELECT" class="correct"><strong>SELECT</strong> - Let the user select among a number of fixed options<a href="#SELECT">#</a></h2>
<p>Don't forget to use a <a href="#LABEL">label</a> for this element too.</p>
<p>It's easy to make selects work without javascript, just add a submit button. Also check so that all options can be reached with the keyboard.</p>
<p>Selects take the size attribute which makes you able to show more than one option at the time. If you set size to something larger than one, you can use CSS to set a height.</p>
<h2 id="SMALL" class="incorrect"><strong>SMALL</strong> - Presentational way of setting font-size<a href="#SMALL">#</a></h2>
<p>Don't use. A presentational way of saying that some text is smaller than the rest. Use <code>font-size</code> in CSS instead!</p>
<p>I've seen some interesting ideas of using this tag for "fine print", those copyright messages that always are tiny. The idea is that the size really is tied to the content, and that small therefore is a good semantic way of representing it. I'm not sure, for now I won't recommend people using it.</p>
<h2 id="SPAN" class="correct"><strong>SPAN</strong> - Similar to <a href="#DIV">div</a> but for inline elements<a href="#SPAN">#</a></h2>
<p>Can be used when you don't find a better representation. Make sure the class you set describes what you mark up instead.</p>
<h2 id="STRONG" class="correct"><strong>STRONG</strong> - Mark something as very important<a href="#STRONG">#</a></h2>
<p>Stronger than emphasis with the <a href="#EM">em element</a>.</p>
<h2 id="STYLE" class="correct"><strong>STYLE</strong> - Add style info to your page<a href="#STYLE">#</a></h2>
<p>Needs to be in the head section of the page, inside body isn't valid.</p>
<p>Don't forget to set the type attribute to "text/css".</p>
<p>In my opinion, using <a href="#LINK">link</a> separates the design better than using the style element. It also makes the browser able to cache the CSS.</p>
<h2 id="SUB" class="almost"><strong>SUB</strong>, <strong>SUP</strong> - Raised and lowered characters<a href="#SUB">#</a></h2>
<p>Don't use for lowering and raising letters with no semantic meaning.</p>
<p>Use in math or chemical formulas (see comments).</p>
<h2 id="TABLE" class="correct"><strong>TABLE</strong> - Row and column based data<a href="#TABLE">#</a></h2>
<p>Misused in the "tables for layout" days. Tables. Are. Not. For. Layout.</p>
<p>Proper use is for scientific, statistical, or other cell-based data.</p>
<p>Frequently forgotten elements include the <a href="#THEAD">thead</a>, <a href="#TBODY">tbody</a>, and <a href="#TH">th</a> elements.</p>
<p>If you nest tables you are doing something wrong.</p>
<p>You can set <code>border-collapse: collapse;</code> to get rid of the annoying default cellpadding. No attributes need to be set in the HTML.</p>
<p>Combining border-collapse and a border on <a href="#TD">td elements</a> makes it possible to get nice 1 pixel borders between all cells.</p>
<h2 id="TBODY" class="correct"><strong>TBODY</strong> - Container meant to separate the body of your table from your headers<a href="#TBODY">#</a></h2>
<p>Simply use this as a way to style your body different from your headers. Have <a href="#TH">th elements</a> both in the tbody and thead? Then use <span class="... "><code>tbody th</code></span> to style only the ones in the header.</p>
<p>You can use several tbody elements, something that can be a nice way to divide one big table into several logical parts.</p>
<h2 id="TD" class="correct"><strong>TD</strong> - Represent one cell of data<a href="#TD">#</a></h2>
<p>Use padding, margin and border on td and th to change the spacing inside your table.</p>
<h2 id="TEXTAREA" class="correct"><strong>TEXTAREA</strong> - Let users send big chunks of text<a href="#TEXTAREA">#</a></h2>
<p>The size can be specified with height and width in CSS.</p>
<p>Don't forget a corresponding <a href="#LABEL">label element</a>.</p>
<h2 id="TFOOT" class="correct"><strong>TFOOT</strong> - Extra information in the bottom of a table<a href="#TFOOT">#</a></h2>
<p>I rarely use this one, most often a caption is what I want below.</p>
<p>A possible use case for tfoot is for adding column sums at the bottom of the table.</p>
<h2 id="TH" class="correct"><strong>TH</strong> - Specify that a certain cell is not part of the data, it just describes the other cells.<a href="#TH">#</a></h2>
<p>Very convenient way of specifying a different style for the headers of the table.</p>
<p>Takes the scope attribute if you want to specify what cells a certain table header describes.</p>
<h2 id="THEAD" class="correct"><strong>THEAD</strong> - Container for (some of) the metadata for a table<a href="#THEAD">#</a></h2>
<p>Some browsers repeat this element on all pages when printing long tables, very useful!</p>
<h2 id="TITLE" class="correct"><strong>TITLE</strong> - Topic of the page summarised in a few words<a href="#TITLE">#</a></h2>
<p>Single most important part of your site, think a while before setting it.</p>
<p>Meant for a single page, not the whole site.</p>
<p>Required for validation, and gives strange validation errors about "head not closed" if not included.</p>
<h2 id="TR" class="correct"><strong>TR</strong> - Way of specifying rows of table cells<a href="#TR">#</a></h2>
<p>Very few browsers support styling the tr element, so set your styles on the containing table cells instead. Example: If you want alternating row colors you can set a class on the tr element but style the table cells with <span class="background: ... "><code>tr.odd td</code></span>.</p>
<h2 id="TT" class="incorrect"><strong>TT</strong> - Text formatted like if it was written on a typewriter<a href="#TT">#</a></h2>
<p>Don't use. Presentational way of adding text that looks like it was written on a typewriter. Use <code>font-family: monospace;</code> to get the same effect with CSS.</p>
<h2 id="UL" class="correct"><strong>UL</strong> - List where the order doesn't matter<a href="#UL">#</a></h2>
<p>Perfect for navigation menus, don't use br for that.</p>
<p>See tip on cross browser use with the ol element.</p>
<h2 id="VAR" class="almost"><strong>VAR</strong> - Variable of some kind<a href="#VAR">#</a></h2>
<p>Another element from the computer science area. Some people claim this can be used for other variables too, but that's a really rare use case. No need to remember.</p>
<p>What did I miss? Please leave a comment!</p>
Don’t use "Divs for layout" please2006-09-11T22:07:23+02:002006-09-11T22:07:23+02:00http://friendlybit.com/css/dont-use-divs-for-layout-please/Emil StenströmProud people all over the world show their new sites and proudly proclaim: "I used divs for layout!" There's a problem with the above. Every time someone...
<p>Proud people all over the world show their new sites and proudly proclaim: "I used divs for layout!"</p>
<p>There's a problem with the above. Every time someone uses the phrase "Divs for layout" they spread the misconception that divs are some special kind of element. Beginners are tricked into thinking that everything you add to a page should be in a div. I've seen great looking pages filled with; you guessed right, only divs.</p>
<p>Some would say that these types of sites actually are worse than table sites. I don't agree. If you look at it in a wider perspective these people at least are on the right track. They are slowly learning and I as I've tried to convey earlier I think it's ok to start out bad and gradually improve.</p>
<p>So, why is it so bad using only divs? Because the idea of HTML is to convey structure. What structure does your content have? Are some parts more important than others? Are you using lists, but not the list element? Find the tags that best fit your particular purpose. There's <a href="http://www.w3schools.com/tags/default.asp" title="Elements available in HTML 4">lots of elements</a> out there. Any good front-end web developer should know (almost) all of them.</p>
<p>Now, could we please stop using the phrase "Divs for layout"? If you want an alternative I would say "CSS for layout". Spread the word my friends!</p>
IE6 resize bug (position: relative becomes fixed)2006-09-04T22:08:49+02:002006-09-04T22:08:49+02:00http://friendlybit.com/css/ie6-resize-bug/Emil StenströmOne bug kept popping up on the sites I built, and I was almost going insane. The bug I'm talking about is specific to Internet Explorer 6 (IE6) and has to...
<p>One bug kept popping up on the sites I built, and I was almost going insane. The bug I'm talking about is specific to Internet Explorer 6 (IE6) and has to do with what happens when you resize the page. Here's an <a href="/files/ie6resizebug/" data-no-instant>example page showing the bug</a>. Open it in IE6 and try resizing the window. Let me explain:</p>
<blockquote>
<p><strong>Update</strong>: <a href="/css/ie6-resize-bug/#comment-4551">Paula comments</a> that IE7 beta 2 has the same problem. Thanks Paula.</p>
</blockquote>
<h2 id="setting-up-the-ie6-resize-bug">Setting up the IE6 resize bug<a href="#setting-up-the-ie6-resize-bug">#</a></h2>
<p>To see the bug in action you need two things: You need to center your page using the body element and you need to be using a fixed width (not percent) on the element. If you use this you will quickly notice that all elements you set <code>position: relative</code> on, will stay fixed on the page when you resize the window. They behave as if you just set position: fixed on them, but only until you reload. It's really a fun effect (if you know the fix).</p>
<p>Example code:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">body</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">margin</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kc">auto</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">760</span><span class="kt">px</span><span class="p">;</span><span class="w"> </span><span class="c">/* Any fixed or fluid width */</span>
<span class="p">}</span>
<span class="c">/* Affects all elements with position: relative; */</span>
<span class="p">#</span><span class="nn">example</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">relative</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Here's a live example of the <a href="/files/ie6resizebug/" data-no-instant>IE6 resize bug</a> with borders added for clarity.</p>
<p>The bug is kinda rare you could say. But using body for centering is a great way of getting rid of one extra container div, so I have been using it more and more lately (IE5 can't handle that, but you don't support it do you?). Anyway, not being able to use <code>position: relative</code> is not ok.</p>
<h2 id="making-things-behave-as-normal-again">Making things behave as normal again<a href="#making-things-behave-as-normal-again">#</a></h2>
<p>Fortunately the fix is very easy. You simply add <strong>position: relative to the body element</strong>. *Blam* All previous broken elements start behaving like expected again. Here's the same <a href="/files/ie6resizebug/fixed.html" data-no-instant>example with the bug fixed</a>.</p>
<p>That's a couple of hours less IE6 adoption time on my next project. I hope it helps someone out there too.</p>
Why XHTML is a bad idea2006-08-27T15:11:26+02:002006-08-27T15:11:26+02:00http://friendlybit.com/html/why-xhtml-is-a-bad-idea/Emil StenströmXHTML is often mentioned when you talk about web standards of different kinds, and many believe that it's the future of the web. I'm of a different opinion...
<p>XHTML is often mentioned when you talk about web standards of different kinds, and many believe that it's the future of the web. I'm of a different opinion and this article explains my reasoning.</p>
<ul>
<li><a href="#history">Some HTML history</a></li>
<li><a href="#xml">XML enters the scene</a></li>
<li><a href="#xhtml">"Let's make HTML work like XML"</a></li>
<li><a href="#problems">Problems with using XML on the web</a></li>
<li><a href="#beginners">We can't expect beginners to use XHTML</a></li>
</ul>
<h2 id="history">Some HTML history<a href="#history">#</a></h2>
<p>A long time ago, in 1990, the first pieces of HTML came to use. It was built specifically for scientific documents and contained nothing by structural elements. The idea was that the user should be the one deciding what a certain document looked like; after all, you read reports for their content, not for their looks. The target audience for HTML was pretty clear, scientists and other computer literate people: programmers in some sense.</p>
<p>The web soon became mainstream. Everyone has now surfed the web and lots of people have their own websites. But far from everyone care for code quality and most websites contain serious code errors. Despite the errors it's worth to remember than most sites "work", that is, they display like the authors want. All thanks to the error-handling of the current browsers.</p>
<p>An angry community of programmers/webmasters has complained about bad code since the beginning and demanded that we force people to only produce valid code. I've been a part of this group in the past…</p>
<p><img src="/images/item_xml.gif" alt="XML icon" class="secondary" /></p>
<h2 id="xml">XML enters the scene<a href="#xml">#</a></h2>
<p>Around 1998 the specification for the XML language was released. XML is a language that makes it easy to construct your own languages. Think of it like HTML, but where you make up your own tag names, and where errors are not allowed. The programmers took it in as their new favourite and it spread quickly.</p>
<p>XML has very precisely defined error-handling (unlike HTML): when the parser finds something unexpected it just stops and displays an error. This means two things: it makes editing XML documents closer to "real programming" (if you make a small error it doesn't compile), and since you don't need code for error-handling the parsers become both faster and easier to write. As you can imagine the programmers felt at home.</p>
<h2 id="xhtml">"Let's make HTML work like XML"<a href="#xhtml">#</a></h2>
<p>W3C was founded and the programmers from the angry HTML community had made an impression on them. They decided to do something about the lousy code people wrote and standardized a new language for the web. XHTML takes the tags from HTML but adapts the language so that it becomes compatible with XML. The result is a language that can (and should) be parsed with an XML parser.</p>
<p>So all is well then? No. As you poke around you'll soon notice that it's pretty damn hard to get XHTML parsed with an XML parser in current browsers. Let me explain: to decide what parser to use you need to send the correct MIME-type from your server. If you're using PHP you can do it like this:</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span> <span class="nb">stristr</span><span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s2">"HTTP_ACCEPT"</span><span class="p">],</span><span class="s2">"application/xhtml+xml"</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="nb">header</span><span class="p">(</span><span class="s2">"Content-type: application/xhtml+xml"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nb">header</span><span class="p">(</span><span class="s2">"Content-type: text/html"</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></div>
<p>That pretty much asks the browser if it can handle XML and if it can sends the XML MIME-type "application/xhtml+xml". If it can't handle it (Internet Explorer 6 and 7 can't) it gets fed the old MIME “text/html” (and errors are tolerated and corrected).</p>
<p>But that’s not the only change you need. In the late 2004, Ian Hixie wrote <a href="http://hixie.ch/advocacy/xhtml">Sending XHTML as text/html Considered Harmful</a> (quite technical). As you read through it you see that you have to change a lot more than the MIME if you want your XHTML to work as intended. Summary: doing it the right way is hard.</p>
<p><img src="/images/item_invalid.jpg" alt="Screenshot of invalid XHTML" class="secondary" /></p>
<h2 id="problems">Problems with using XML on the web<a href="#problems">#</a></h2>
<p>So XHTML is hard to get parsed the intended way in current browsers. Instead most people using it decide (or don't know otherwise) to parse it like if it was HTML. But doesn't that defeat the biggest reason to user XHTML in the first place? The only big difference between HTML 4.01 and XHTML is that XHTML can be parsed as XML! <em>As long as you parse your code as HTML there's no reason to use XHTML</em>.</p>
<p>If we have a look at the specification of XHTML there's a little table displaying <a href="http://www.w3.org/TR/xhtml-media-types/#summary">what versions of XHTML that should be sent with what MIME type</a>. You'll see that it's ok to send XHTML 1.0 as text/html (may). But looking forward to later versions you see that they "should not" be sent as XHTML. So pretty soon, parsing XHTML as HTML will not be allowed if you want to follow the standards. That leaves parsing it as XML.</p>
<p>Imagine some kind of dynamic site that allows readers to add content to it. The comments of this site are a good examples. If I used XHTML (and parsed it properly) and someone used invalid code in the comments the page would break. New users to the site would get a big and ugly error message with a line number and some code. Totally unacceptable. So I would have to find a way to parse the HTML in my comments and fix errors that could break the page. Ok.</p>
<p>Next I copy-paste some text from a site I want to quote to you. When I publish the article I get a big ugly error message because the site I pasted used another character encoding and that breaks my XHTML. I research the problem and find that this could be fixed by parsing all text in my admin console and making sure it's valid UTF-8 before storing it in the database. Ok.</p>
<p>Next I download a bit of javascript and try using it on the site. Again people get an ugly error message in their face when they enter. It seems javascript is handled a lot stricter in XHTML and inline javascript needs some strange CDATA characters at the beginning and end of the script element. Ok, so I fix that too.</p>
<p>And like that it continues, tiny differences in code makes the page break over and over again, and bugs in the parsers I write makes people able to break my site by posting content. I have a computer science education behind me, so I could probably fix the errors and keep patching the site until everything works. But do I want to? What's wrong with the current way of fixing errors when I notice them when validating? And what about all the non-programmers?</p>
<h2 id="beginners">We can't expect beginners to use XHTML<a href="#beginners">#</a></h2>
<p>As you've read above it's damn hard to get XHTML right. Still the W3C pushes for XHTML as the new standard for the web. Despite how hard it will be for beginners to get things right. Despite that you will move error handling to the parsers of each website instead of the browsers. Despite that XHTML has almost no backwards compatibility so pretty much <strong>all</strong> sites on the entire web will have to update their code.</p>
<p>No, I won't parse things as XML on the sites I build. XHTML was a bad idea from the start and I'd rather go with the new version of HTML developed under the name <a href="http://whatwg.org/specs/web-apps/current-work/">Web Applications 1.0</a> (also known as HTML 5).</p>
<p>I hope this article explains why a lot of web development blogs (including Friendly Bit) use HTML. What language do you use?</p>
<blockquote>
<p><strong>Update</strong>: More reasons why you should use HTML</p>
</blockquote>
KTH goes web standards2006-08-23T00:36:28+02:002006-08-23T00:36:28+02:00http://friendlybit.com/css/kth-goes-web-standards/Emil StenströmSweden's largest technological university, KTH, just launched their new site and I'm proud to say that I've been responsible for the HTML and CSS for it....
<p>Sweden's <a href="http://www.kth.se">largest technological university, KTH</a>, just launched their new site and I'm proud to say that I've been responsible for the HTML and CSS for it. I'd thought I'd take some time and tell you about the techniques I used and the reasons behind using them. Let’s start with some background:</p>
<p><a href="http://www.kth.se"><img src="/images/item_kth.jpg" alt="Blue KTH logotype" class="secondary" /></a></p>
<h2 id="about-kth">About KTH<a href="#about-kth">#</a></h2>
<p>KTH is an initialism for "Kungliga tekniska högskolan" which translates to "Royal Institute of Technology" in English. It's the biggest technology focused university in Sweden with almost 17000 registered students for 04/05 (<a href="http://www.scb.se/statistik/UF/UF0205/2005A02/Web_GR1_RegUnivKon.xls" title="Number of registered students on KTH">source</a>). Add over 3000 employees to that and you'll start to see the number of people affected by the update. KTH hosts a lot of content, <a href="http://www.google.com/search?hl=en&q=site%3Akth.se">Google reports 1,930,000 pages</a>. Not all pages are included in current the update, but it gives a pointer to what kind of site we are looking at. In summary, a standards based update of KTH affects a lot of people.</p>
<h2 id="polopoly-and-the-html">Polopoly and the HTML<a href="#polopoly-and-the-html">#</a></h2>
<p>I entered the project quite late in the process (<a href="/css/valtech-my-new-employer/">Valtech found me</a>), about a month before launch. Most of the back-end work had already been completed and authors responsible for different parts of the organisation had started filling the database with content. The CMS used was a platform known as Cortina, based on top of the CMS framework <a href="http://www.polopoly.com">Polopoly</a>.</p>
<p>Everything was modular and the changes I wanted to do to the HTML nicely cascaded out over the site. When you look at the HTML you'll notice that it contains a lot of strange whitespace, making the code somewhat difficult to read. That's because of the template language used, <a href="http://java.sun.com/products/jsp/jstl/">JSTL</a>, which leaves whitespace after each element. I therefore recommend using the <a href="http://users.skynet.be/mgueury/mozilla/">HTML validator extension for Firefox</a> , selecting view source, and then using the button "Clean up the page" in the bottom right corner. That makes the code a bit easier to read for you on the outside. I hope you won't be too upset over that :)</p>
<p>You'll find that all new pages validates as HTML 4.01 Strict (or at least very close, I know of some ampersand encoding errors on one page) and I'm very proud of the outputted HTML. It maps the structure of the content nicely and is easy to browse without CSS enabled. It contains very few elements that are there just as "style hooks" and the id and class names describes the contents of the elements, not their design.</p>
<h2 id="css-and-the-techniques-used">CSS and the techniques used<a href="#css-and-the-techniques-used">#</a></h2>
<p>The new site makes full use of CSS for its layout. We targeted mainly Firefox 1.5 and Internet Explorer 6 with the new site but using web standards I wouldn't be surprised if it works well in other modern browsers too. For those of you that like fancy terms I can say that the site is a fixed width, zoomable, source ordered, 3 column equal height layout. I'll talk a little about the fancy terms above and explain the reasoning behind them.</p>
<p><img src="/images/item_ruler.jpg" alt="Image of a Ruler" class="secondary" /></p>
<h3 id="fixed-width-layout">Fixed width layout<a href="#fixed-width-layout">#</a></h3>
<p>Let's start with the most controversial of the design decisions. The site is optimized for 1024×768 pixel resolutions and up. This was a hard decision but given the content of the site, the design at hand, and the target audience we felt that it was a good one. Let me explain our reasoning:</p>
<p>KTH has a lot of information to display. Many different parts of the site need to get exposure and the wider 1024 format made that possible. Many of the images were also designed for the wide format and changing the width would mean we would have to examine all of them and decide how to cut each one. Surf around on the site and you'll see the problems that would bring. Objects in images, meant to be centered, would be offset and some items would be cut. Those content and design issues, together with the somewhat "technological" target audience, convinced us that 1024 was the right decision.</p>
<h3 id="zoomable-layout">Zoomable layout<a href="#zoomable-layout">#</a></h3>
<p>We wanted to make the user able to change the font-size if they wanted to. This meant that quite a few boxes needed to expand with the text, to prevent the text from overflowing them. This was solved by selectively using em units making the boxes expand with the text-zoom. This worked well, and I'm especially proud of the <a href="http://www.kth.se" title="KTH:s front-page">front-page</a>, with all the different elements expanding and collapsing together. There are a few glitches in the zoomed layouts, a couple of pixels missing here and there, but from the testing we have done those are few (there’s currently one line too much content in the middle box, making the zooming uneven, don’t worry about that :).</p>
<p><img src="/images/item_order.jpg" alt="List of groceries in order" class="secondary" /></p>
<h3 id="source-ordering-and-skip-links">Source ordering and skip links<a href="#source-ordering-and-skip-links">#</a></h3>
<p>The layout is a rather typical 3 column layout with a header and footer. The leftmost column is for navigation, the middle one for the real content, and the right one for additional information. In terms of importance the content is the most important, followed by the additional information column, followed by the navigation. This called for use of a technique known as source ordering, having the content in one order structurally and in another visually.</p>
<p>Using source ordering is a good way of making it easier for non visual browsers (screen readers, text browsers, and search engines) to get the most important information first. This is not the right article to explain the method in full (some wrapper divs and some clever floats); I'll save that for a later article. Anyway, what matters is that there are some advantages to using this method and that we decided to use it.</p>
<p>Others prefer to be able to jump to whatever place in the source they want. For this, "skip links" are quite effective. Skip links are internal links (links pointing to an id somewhere on the same page) that you put in the beginning of the HTML. Clicking the link moves the focus to the corresponding place in the content. We felt that this was a simple way to provide navigation for users with CSS disabled. The skip links where hidden for everyone else.</p>
<h3 id="3-column-equal-height">3 column equal height<a href="#3-column-equal-height">#</a></h3>
<p>As many of the column layouts today this one was made with all columns of equal height. It's a common complaint amongst the "table for layout" users that these kinds of layouts are too hard to do with CSS. They are not. An easy technique for doing this is known as <a href="/files/templates/?style=faux_columns&cols=3&nofooter=1" data-no-instant>faux columns</a> and is simply: putting your columns in a wrapper, floating them left, and setting a background image in the wrapper. The wrapper expands whenever any of the columns expand and shows more of the tiled background image as needed. It's a simple technique, it works well, doesn’t contain any hacks, and is easy to learn. CSS vs. Tables: 1 - 0.</p>
<p><img src="/images/item_matrixd.jpg" alt="One of the 5 layouts available" class="secondary" /></p>
<h3 id="front-page-grid">Front page grid<a href="#front-page-grid">#</a></h3>
<p>One of my favourite parts of the site is a feature that most users only will notice over time: The top left part of the front page can be switched between five different layouts, depending on what the editors feel fits their content best. This means that the editors are given a big chance to "design" the front page; a very nice move from the designer.</p>
<p>For me, as the one responsible for implementing this, I had a couple of though days. But I learnt a lot and ended up using a min-height set with em units on the different boxes. This way I could make boxes at totally different parts of the page zoom together. IE6 handles height as min-height so setting "fixed" heights in a separate file for IE ensured that the design worked there too. After using and testing this method for a couple of weeks I must say that I like the it, it gives me a nice grid to work with, but not a fixed one as with tables. This one expands depending on what the content requires. I recommend you to try it out.</p>
<h3 id="conclusion">Conclusion<a href="#conclusion">#</a></h3>
<p>The developers behind the new KTH website have constructed a site that was incredibly fun to work with. I consider myself lucky to having worked with such a good team and have learnt a lot in the process.</p>
<p>Also, as a student of KTH for many years I know that the site will be well received by fellow students; and at the end of the day, isn’t that what matters?</p>
Valtech: my new employer2006-08-22T21:20:29+02:002006-08-22T21:20:29+02:00http://friendlybit.com/css/valtech-my-new-employer/Emil StenströmJust wanted to let you know that I have accepted a job at Valtech. My title will be "technical consultant" (which could mean anything, I know :), and you...
<p>Just wanted to let you know that I have accepted a job at <a href="http://www.valtech.com">Valtech</a>. My title will be "technical consultant" (which could mean anything, I know :), and you have probably already guessed that I will be focusing on HTML and CSS; interface design in different forms. I started working last Thursday so today was my fourth day and I must say that I really like it there. A friendly atmosphere amongst (very) skilled developers is what I've seen so far, and I know how much that counts when it comes great results.</p>
<p>Anyway. I'm sure you'll just think I'm practicing my sales speak so I'll stop there :) (I’m not damnit!). As I said I'll be working as a consultant, which means I'm dependent on customers wanting interfaces made. So feel free to <a href="/contact/">contact me</a> or <a href="http://www.valtech.se/templates/Page.aspx?id=2057">my employer</a> (Swedish link) if you have an interesting project you need help with.</p>
<p>(Don't worry, I won't stop posting here, I have a big post about my first project coming up)</p>
Tricks to make your site easier to use2006-08-01T19:17:40+02:002006-08-01T19:17:40+02:00http://friendlybit.com/html/make-your-site-easier-to-use/Emil StenströmThere are lots of little tricks you can use to make your sites easy to use. Problem is that they are so obvious, you don’t think of them. This article is an...
<p>There are lots of little tricks you can use to make your sites easy to use. Problem is that they are so obvious, you don’t think of them. This article is an attempt to share some of the ideas that I <em>did</em> think of. I'm sure I missed some; feel free to add your own tricks in the comments.</p>
<p>You rarely think of sites as "easy to use"; they just work. You enter them, click here and there, and don't think much about how the navigation works or what to do. That's the feeling we should go for.</p>
<h2 id="separate-the-interaction-layer">Separate the interaction layer<a href="#separate-the-interaction-layer">#</a></h2>
<p>A very simple way of making it easier for your users is clearly marking what can be interacted with. Are users expected to click on those small arrows of yours? Are the only links to your content through your headers? Then you better make sure those arrows or headers come across as clickable.</p>
<p>The fastest way to convey that something is clickable is using blue underlined text. Why? Because that's what most sites use (see <a href="http://www.google.com">Google</a>, <a href="http://www.amazon.com">Amazon</a>, <a href="http://www.ebay.com">eBay</a>). It's what we have grown up with and it just works. Designers tend to dislike blue underlined links and have started to use other colors and skip the underlines. Jakob Nielsen, the notorious usability expert, writes about what you should think of in his <a href="http://www.useit.com/alertbox/20040510.html">article about the visual style of links</a>. It's a good reminder.</p>
<p>You don't have to stop with just the links though. Are your images clickable? Then make sure they connect with your links somehow. If you pick orange as your link color, make something around or in the images use that color too. Make your form fields use the same color. When someone enters your site it should be possible to quickly get an idea of what to do: "I can either click a link in the menu, search for a phrase, or click this thumbnail". Don't make people confused by mixing in orange on the static parts of your site.</p>
<p>With some cleverness I'm sure this idea can be expanded to work even without being dependent on color. A small figure? A border? Use your imagination, and be sure to tell me about it.</p>
<h2 id="split-up-your-content">Split up your content<a href="#split-up-your-content">#</a></h2>
<p>You know those portal sites? There's one big reason they don't work. There's too much content cramped into a too small area. A portal is rarely about something specific, it's about everything that they can possibly fit in. Whatever content you are looking for you will have to search hard for it. Do you use the portal parts of Yahoo or MSN? Didn't think so.</p>
<p>There has been a long discussion recently about how badly designed pages work better. <a href="http://www.andyrutledge.com/bad-design.php" title="Bad design harms business, it does not help it">Like Andy Rutledge</a> I mostly disagree but I can understand how bad design works for ad-driven sites. Is the point of your pages to make people click ads? Then make them confused, make them think your navigation is the ads, I'm sure it drives your revenue up. If the point of your site is the content on it, stay away from being a portal.</p>
<p>The simplest way of avoiding the portal-look is splitting up your content. Do you have info on both crocodiles and stock numbers? Don't put them on the same page. Make sure only the people interested in stocks get the stock info. Anyone else will just see them as "something I am not looking for". If you have lots of info from diverse fields, perhaps a <a href="http://dmoz.org/" rel="nofollow">directory</a> is a better bet?</p>
<h2 id="use-codeltlabelgtcode-for-form-elements">Use <code><label></code> for form elements<a href="#use-codeltlabelgtcode-for-form-elements">#</a></h2>
<p>Bad form elements are one of the most annoying things on the web. Worst are those tiny little checkboxes you need to check to specify if you like to get spammed or not. They are simply too small. There is an easy solution though, that everyone should be aware of: the label element. What it does is associate some text with the checkbox. The browsers use this information by making a click on the text check the box. Note: this also works for radio buttons. Here's the markup you need:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">form</span> <span class="na">action</span><span class="o">=</span><span class="s">""</span><span class="p">></span>
<span class="p"><</span><span class="nt">input</span> <span class="na">checked</span><span class="o">=</span><span class="s">"checked"</span> <span class="na">id</span><span class="o">=</span><span class="s">"send_spam"</span> <span class="na">type</span><span class="o">=</span><span class="s">"checkbox"</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
<span class="p"><</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"send_spam"</span><span class="p">></span>Send me all your "newsletters"<span class="p"></</span><span class="nt">label</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
<span class="p"></</span><span class="nt">form</span><span class="p">></span>
</pre></div>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">label</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">cursor</span><span class="p">:</span><span class="w"> </span><span class="kc">pointer</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>There's a lot more to learn about how to make your forms usable and accessible. Just head over to the Web standards project's <a href="http://www.webstandards.org/learn/tutorials/accessible-forms/beginner/">Accessible forms tutorial</a> (don't miss the intermediate one either).</p>
<h2 id="make-it-interesting">Make it interesting<a href="#make-it-interesting">#</a></h2>
<p>You have a few seconds to get you visitor hooked to your site. In that time the user needs to understand he's on the right track. "Ah, this site seems to be about web development" is what I want my users to feel when they enter Friendly Bit. Therefore almost all my pages have a little info box that tells the visitors just that. To just put this info on your front page isn't enough, search engines or other external links can make them enter deeper into your site. Please put this little info-box somewhere on all of your sites. It's one of the best ways for me to see I'm where I want to be.</p>
<p>To actually get your content interesting you need to work on your writing. My best tip is to follow the points Liz Strauss summed up nicely in her post about <a href="http://www.successful-blog.com/1/9-1-things-every-reader-wants-from-a-writer/">what a reader wants</a>.</p>
<p>Read through your text over and over again, out loud if you need to. Pay attention to typography, don't make your paragraphs too long and use headers extensively.</p>
<h2 id="conclusion">Conclusion<a href="#conclusion">#</a></h2>
<p>These are just some of the tricks I find myself using on my sites. I'm sure this site does not follow all of them perfectly but that doesn't stop me from telling you about them, does it? Pick and choose as you like, but try to reach make you visitors feel that "it just works"-feeling.</p>
<p>Do you have any tricks you can share?</p>
Correcting the 20 pro tips (.NET magazine)2006-07-26T05:01:06+02:002006-07-26T05:01:06+02:00http://friendlybit.com/css/correcting-the-20-pro-tips/Emil Stenström.NET magazine is a fairly big web development magazine. I've recently been referenced to its articles from many separate places, and often found the...
<p>.NET magazine is a fairly big web development magazine. I've recently been referenced to its articles from many separate places, and often found the articles to be of good quality. The last one, called <a href="http://www.netmag.co.uk/zine/design-tutorials/20-pro-tips">20 pro tips</a>, was not too good though, so I'm going to go through and correct it. I'm not trying to attack the magazine here (remember "friendly" in the URL), I just want people to know these things.</p>
<p>The article consists of 20 points that a pro should know. Here are the points I found errors in:</p>
<h2 id="stylesheets-importing-vs-linking-point-3">Stylesheets: importing vs linking (point 3)<a href="#stylesheets-importing-vs-linking-point-3">#</a></h2>
<p>The point is that importing is better than linking since many older browsers will not apply the CSS then. This is correct but they also go as far as suggesting developers to add a separate stylesheet for Netscape 4 (NS4). As someone that has experimented with NS4 I can say that its CSS support is bad. Really bad. Considering the near zero percent of NS4 users I would strongly advise against fixing your site for it. That is of course, unless your site logs suggests you have a lot of users with that (old) browser.</p>
<p>There's also a code error here, simple.css is included twice, and the second @import reference should probably be advanced.css. Not a big error but might confuse someone.</p>
<h2 id="smarter-gradient-backgrounds-point-4">Smarter gradient backgrounds (point 4)<a href="#smarter-gradient-backgrounds-point-4">#</a></h2>
<p>Again a good point. CSS can be used to repeat background images on any element, not just body. This means you can save on file size by replacing big images with smaller ones. The article then suggests using 1 pixel wide images which is something old versions of IE has problems with. A lot of repetitions can easily get the browser very slow so my best bet would be to make them at least 5 pixels wide.</p>
<p>In the code you would be better off using shorthand notation (I know, this is not a big deal). To add an extra pedagogic twist something else than body could have been used:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">form</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="kc">white</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="sx">background.png</span><span class="p">)</span><span class="w"> </span><span class="kc">repeat-x</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<h2 id="ie-box-model-hack-point-8">IE Box Model Hack (point 8)<a href="#ie-box-model-hack-point-8">#</a></h2>
<p>A lot of confusion here. Internet Explorer 5 (IE5) uses another box model than the modern browsers. The padding and border are not added to the outside of a specified width, but instead included in it. This means that if you specify a 500 pixel wide box and add a 10 pixel border to it, it will still be 500 pixels wide. Some say that this is a better way of calculating widths but that's missing the point. The point is that according to the W3C box model the padding should be added <em>outside</em> of the width.</p>
<p>This problem does not appear in Internet Explorer 6 (IE6) if you <a href="/css/cross-browser-strategies-for-css/#mode">include a proper Doctype</a>.</p>
<p>So IE5 is broken, should you care? Again, check your logs if people still use the ancient IE5. My guess is that they don't which saves you a lot of work. There's probably <em>no need for this hack</em>.</p>
<p>Also, the <a href="http://tantek.com/CSS/Examples/boxmodelhack.html">Box model hack</a> is Tantek's hack using the voice-family property to add a "}" to your CSS. It's really ugly. The article uses the same name for another solution to the problem: wrapping the offending element in another element and moving the padding to that box. That's a much cleaner way of fixing the problem.</p>
<h2 id="space-saver-point-9">Space saver (point 9)<a href="#space-saver-point-9">#</a></h2>
<p>Don't use inline styles for styling. Try to keep all your styles in the external CSS file. Two more general ways of saving space across browsers are outlined in my <a href="/css/cross-browser-strategies-for-css/#default">cross-browser CSS article</a> (the star-selector and using a premade CSS file that resets browser defaults.</p>
<h2 id="format-fundamentals-point-11">Format fundamentals (point 11)<a href="#format-fundamentals-point-11">#</a></h2>
<p>Good points about image formats. Use 8-bit PNGs instead of GIF, it makes you smaller files.</p>
<p>An addition: JPEGs are generally smaller than 32-bit PNGs but that's because JPEG removes information in your image to improve compression. Remember that, if you use JPEG.</p>
<p>If you use PNG you need to know that IE has problems showing them in the exact correct color (<a href="http://hsivonen.iki.fi/png-gamma/">technical explanation of the PNG color problem</a>). If that matters a lot to you, use another format (remember that all PNGs change color in IE, so images still match each other). Friendly Bit uses PNGs only.</p>
<h2 id="the-title-and-alt-attributes-point-12">The ‘title’ and ‘alt’ attributes (point 12)<a href="#the-title-and-alt-attributes-point-12">#</a></h2>
<p>Don't use the title attribute unless it's needed to convey what you mean. In the example it does not make sense at all, why repeat the alt text? The main point is still true though, always use the alt attribute and make good use of the title attribute.</p>
<h2 id="wrapping-text-around-images-point-17">Wrapping text around images (point 17)<a href="#wrapping-text-around-images-point-17">#</a></h2>
<p>Come on! Using the align attribute is going against what was just recommended, use of semantic markup (point 14). Alignment is style and should be added through CSS, nothing else. Adding a strict Doctype and validating will generate an error on this kind of ugliness. Use <span class="float: left "><code>img.typeOfImage</code></span> instead.</p>
<p> </p>
<p class="first">
That's it for now, hope you learned something. I just wanted to make sure my readers know more than the .NET readers :)
</p>
Carnival and Site updates2006-07-24T17:11:39+02:002006-07-24T17:11:39+02:00http://friendlybit.com/other/carnival-and-site-updates/Emil StenströmHi all! I just wanted to gather a few things in one big post about this site. Carnival of the Web #2# First and foremost. I'd like to tip you off about...
<p>Hi all! I just wanted to gather a few things in one big post about this site.</p>
<h2 id="carnival-of-the-web-2">Carnival of the Web #2<a href="#carnival-of-the-web-2">#</a></h2>
<p>First and foremost. I'd like to tip you off about <a href="http://www.thefutureoftheweb.com/blog/2006/7/carnival-of-the-web-2">Carnival of the web #2</a>, Jesse Skinner's gathering of the best posts he can find. Proof of its quality? I'm in it :) Keep up the good work Jesse.</p>
<h2 id="featured-on-accessitesorg">Featured on Accessites.org<a href="#featured-on-accessitesorg">#</a></h2>
<p>Secondly. This site has gotten a quite a few small updates lately (I hope it didn't break things for you). The biggest reason for updates is my submission to Accesssites.org a site that aims to be a big gallery of accessible websites. I thought it would be fun to submit and get some feedback on the accessibility features of this site, so I did. I can tell you now that their reviewing was thorough. I got a list back with all problems of the site outlined, down to details. Impressive. It all ended up with Friendly Bit being featured as a "<a href="http://accessites.org/checklist/#chk3">Quality Universal Design</a>" according to them means:</p>
<blockquote>
<p>"The Accessites.org Classic Universal Design Award site shows a thorough attention to detail. This is a great web site on which the developer toiled diligently to get it right. This is the type of website that we can all learn from. For a site like this, the client should be telling everyone they know to hire the project’s developer (in addition to a footer link and icon display, and next project promise)."</p>
</blockquote>
<p>With a score of 24.22 I'm just 0.7 points from the next level, something I'm very happy with. Go ahead and <a href="http://accessites.org/showcase/" title="What Accessites wrote about Friendly Bit">see what they wrote about me</a>.</p>
<p>Anyway. I've made a lot of minor adjustments to this site because of the review. The site now fits into 800 wide screens. It is less confusing with images disbled. The navigation to the right uses underline and not only color as its hover decoration. Lots of little things like that.</p>
<h2 id="updates-to-how-comments-work">Updates to how comments work<a href="#updates-to-how-comments-work">#</a></h2>
<p>Of other reasons I've also tuned the comments a bit. The trackbacks and pingpack got moved down (they were just annoying to anyone trying to follow a discussion). Now you'll find them at the bottom of the article. You will also be able to edit your comment for 10 minutes after it's posted. I'll see how this works for a while, let me know if something breaks (check the contact page for e-mail).</p>
<p>Any other changes you'd like to see?</p>
<p><strong>Update:</strong> Switched to Feedburner for my feeds, let me know if they cause you any trouble.</p>
Why you should date a front-end developer2006-07-22T13:01:31+02:002006-07-22T13:01:31+02:00http://friendlybit.com/other/why-you-should-date-a-front-end-developer/Emil StenströmYou've heard all those rumours of how nerdy looking people in glasses obsess over numbers they call things like "pie" or "eee". You heard they dress up like...
<p>You've heard all those rumours of how nerdy looking people in glasses obsess over numbers they call things like "pie" or "eee". You heard they dress up like aliens and go to big… ehm… seminars, where people sleep in sleeping bags and only eat bad food. Then you have the other side of it, in a couple of years they will have well-paid jobs at some major technological company. They also don't switch partners easily, if they find someone they like they stick to him/her for, like, forever. You might also be able to hold an intellectual conversation with someone from this group, just try to stay away from tech-talk, you don't want get hurt. If you are able to get their eyes off the screen, say hello to <em>the programmers</em>.</p>
<blockquote>
<p>Typical comment: "Linux is much better than Windows"</p>
</blockquote>
<p>On a trendy club in the middle of town you'll find the next group of people. Some of these also have glasses, but not because they need them, more because it makes them look hip. These people never talk directly with the programmers; a few words could easily ruin their reputation completely. While these people also make a lot of money it's more spread out over the year. They sometime get a creative period in January and paint images of pink goats that they sell for thousands of dollars, just to get no ideas at all in February and be broke. People from this group should be interesting if you're in for fame and fortune, passion and flame, but be aware that you might need a couple of partners to switch between depending on their weekly mood. If they get a break in their busy schedule, you should say hello to <em>the designers</em>.</p>
<blockquote>
<p>Typical comment: "Did you see those shoes she was wearing? They where teeeeerrible!"</p>
</blockquote>
<p>In the third corner, not talking with any of the two groups above, we have a smaller group of people. These started as programmers but didn't like sitting isolated in basements. They wanted to work more with people and what people wanted. After studying methods for doing that they suddenly stopped thinking about anything else. They quickly made enemies with the designers because of their often pretty creations that made people go "oh, this looks good" instead of using the product right away. People in this group are great at handling people, and are often good company on dates, that is, if you can take their know-it-all attitude. They tend to know everything that matters and love to tell you about it. They get decent salary and tend to stick with partners that stay "useful" (not too pretty) and focus on right things. If you find the most functional way to say hello you should try it with these people, the <em>usability experts</em>.</p>
<blockquote>
<p>Typical comment: "Door handles are really quite bad, 60% of users would be better off with something else"</p>
</blockquote>
<p>But I'm not here to talk about programmers, designers, or usability experts. I'm here to talk about a fourth group of people. These are the people that all three of the previous actually talk to. Not because they necessarily want to, but because they need it to get things done. These are the people that get frowned upon for being bad programmers, lousy designers, and for knowing too little about usability. Truth is, they still they manage to ship sites that actually work. They tend to be good at coding, but not in the way programmers are used to. While they don't have the status of designers, they are visible in the same way. They are actually good at explaining their thinking to people around them (often without technical experience), and know who they design for. You'll have no problems saying hello to the <em>front-end developers</em>.</p>
<blockquote>
<p>Typical comment: "Don't use tables for layout"</p>
</blockquote>
<p>So, this fourth group of people have all the good characteristics of the other groups. Just like programmers they are able to have an intellectual conversation with someone. If you like the "nerdyness" that pretty much defines programmers, you'll sometimes find it with the front-enders too (just try mentioning that you like XHTML). Like designers they do get some of the fame when a site gets successful, since they are the ones pulling the strings and making things work they are quite visible. But unlike designers, these people will not desert you because you used the same t-shirt two days in a row. As a final strike you'll find that front-enders are good with people, just like the usability experts. They even know about the people that will be using the site and will gladly meet with them if they get the chance.</p>
<p>So front-end developers are simply the best kind of date, so what are you waiting for? Go out there and get one before they run out!</p>
Static and dynamic CSS combined2006-07-16T18:56:03+02:002006-07-16T18:56:03+02:00http://friendlybit.com/css/static-and-dynamic-css-combined/Emil StenströmSome of you have probably heard "dynamic CSS". It originates from a need to serve different CSS at different times, to different people, or on different...
<p>Some of you have probably heard "dynamic CSS". It originates from a need to serve different CSS at different times, to different people, or on different pages. You do this by first generating the CSS on the server and then sending it off to the users requesting it. There are problems though, since the CSS gets regenerated each time you lose the advantage of caching. You could send HTTP headers so that the file gets cached anyway, but then it's no longer dynamic right? This article presents a way to both have dynamic CSS that changes on each request, and make sure the user loads it from cache when it can.</p>
<h2 id="how-dynamic-css-works">How dynamic CSS works<a href="#how-dynamic-css-works">#</a></h2>
<p>Sometimes you want to send a different set of CSS rules depending on what page you are on. An example could be if your site was module based. Depending on what page you surf to you might get a calendar, some list of latest news or a small box showing the weather in, say, Stockholm.</p>
<p>The functionallity is not too hard to build with some server side language, but what about the CSS? Is it really necessary to load the calendar's CSS on the news page, where the calendar is hidden? The same thing applies for each of the modules you have on your site; that list of news has certain CSS rules tied to it that isn't needed on the gallery page. You get the point. So how do we solve this? We could do it my generating it on the fly (I'm using PHP here, but any other language would work):</p>
<p>PHP source:</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="cp"><?php</span>
<span class="c1">// This line makes sure the browser handles</span>
<span class="c1">// the file as CSS and not PHP.</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: text/css'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$module</span><span class="p">[</span><span class="s1">'calendar'</span><span class="p">]</span> <span class="o">==</span> <span class="k">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'</span>
<span class="s1"> .calendar { width: 300px; }</span>
<span class="s1"> .calendar table { background: pink;}</span>
<span class="s1"> '</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$module</span><span class="p">[</span><span class="s1">'newslist'</span><span class="p">]</span> <span class="o">==</span> <span class="k">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'</span>
<span class="s1"> .newslist { list-style: none; }</span>
<span class="s1"> .newslist li { display: inline; }</span>
<span class="s1"> '</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">[</span><span class="k">and</span> <span class="nx">so</span> <span class="nx">on</span> <span class="nx">every</span> <span class="k">new</span> <span class="nx">module</span> <span class="nx">added</span><span class="p">]</span>
<span class="cp">?></span>
</pre></div>
<p>Generated file:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">.</span><span class="nc">calendar</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">300</span><span class="kt">px</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">.</span><span class="nc">calendar</span><span class="w"> </span><span class="nt">table</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="kc">pink</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">.</span><span class="nc">newslist</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">list-style</span><span class="p">:</span><span class="w"> </span><span class="kc">none</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">.</span><span class="nc">newslist</span><span class="w"> </span><span class="nt">li</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">inline</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>You save this file as "dynamic_stylesheet.php" and link it like you would if it was a static CSS file. Everything works fine and all the dynamic CSS makes the file sent to the user quite small. Both you and your users are all happy. The site starts growing.</p>
<h2 id="problems-with-dynamic-css">Problems with dynamic CSS<a href="#problems-with-dynamic-css">#</a></h2>
<p>After a while you start getting reports of the site getting slow. After some research you find that it's in fact the dynamic CSS that does it. The file has gotten quite big and regenerating it each time is a lot of work. So you read up on caching and find that all that's needed is a few lines at the top of your dynamic CSS file:</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="cp"><?php</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Cache-control: must-revalidate'</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Expires: '</span> <span class="o">.</span> <span class="nb">gmdate</span><span class="p">(</span><span class="s1">'D, d M Y H:i:s'</span><span class="p">,</span> <span class="nb">time</span><span class="p">()</span> <span class="o">+</span> <span class="mi">3600</span><span class="p">)</span> <span class="o">.</span> <span class="s1">' GMT'</span><span class="p">);</span>
<span class="cp">?></span>
</pre></div>
<p>This makes the browser load the file from cache for one hour instead of requesting it again. Problem solved! Right? Well, this means that you won't get a regenerated file if you visit a new page on the site. The browser will load the style from cache instead and your users will get an unstyled calendar (or any other module) for an hour. Pretty annoying if you ask me.</p>
<p>Say we solve the problem above and get the page to only get cached on a per page basis. There's still something that feels like a bit of a waste: we require the user to download the entire page again if just one of the modules changes. Say the user moves from the news list to checking out a certain news item. They will probably look pretty much the same, it's just that the news list's CSS won't be needed on the news item page. We would need some way of only telling the browser to only cache parts of the files and make the loading of those parts dynamic.</p>
<h2 id="import-to-the-rescue">@import to the rescue<a href="#import-to-the-rescue">#</a></h2>
<p>Caching only fragments of your style is certainly doable in a lot of ways. The easiest I have found is using CSS's own @import command. You simply change the example above to:</p>
<div class="highlight" data-language="PHP"><pre><span></span><span class="cp"><?php</span>
<span class="c1">// This line makes sure the browser handles</span>
<span class="c1">// the file as CSS and not PHP.</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: text/css'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$module</span><span class="p">[</span><span class="s1">'calendar'</span><span class="p">]</span> <span class="o">==</span> <span class="k">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'</span>
<span class="s1"> @import "calendar.css";</span>
<span class="s1"> '</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$module</span><span class="p">[</span><span class="s1">'newslist'</span><span class="p">]</span> <span class="o">==</span> <span class="k">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'</span>
<span class="s1"> @import "newslist.css";</span>
<span class="s1"> '</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...and so on every new module added</span>
<span class="cp">?></span>
</pre></div>
<p>Generated file:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">@</span><span class="k">import</span><span class="w"> </span><span class="s2">"calendar.css"</span><span class="p">;</span>
<span class="p">@</span><span class="k">import</span><span class="w"> </span><span class="s2">"newslist.css"</span><span class="p">;</span>
</pre></div>
<p>This makes the individual CSS files get cached by the browser (just like directly linking a CSS file would) while still allowing each page to dynamically add the style blocks it needs. A simple solution to a hard problem, just the kind of solutions I like best. What do you think?</p>
Finer details of floats2006-07-09T15:40:06+02:002006-07-09T15:40:06+02:00http://friendlybit.com/css/finer-details-of-floats/Emil StenströmThe other day I was working on one of those two column layouts. I quickly got into trouble by something I thought was a bug. It was a bug, but not in the...
<p>The other day I was working on one of those two column layouts. I quickly got into trouble by something I thought was a bug. It was a bug, but not in the browser(s) I thought. Let's go.</p>
<p>A two column layout I said, but this one was a bit different. Each column consisted of a number of boxes, much like a newspaper kind of layout. I wanted the boxes ordered a bit different though: Content editors on the site ordered articles by importance in a single list and when that was transferred to a two column layout I wanted the second most important article to the right of the first article rather than below it. In the HTML source the boxes were ordered like the editors wanted and my job was to make them display in two columns.</p>
<p><img src="/files/textcolumns/textcolumns.png" alt="Number 1 to the left, number 2 to the right, number 3 below number 1 to the left, number 4 below number 2 to the right and so on..." /></p>
<p>"This can't be that difficult" I thought and floated all odd numbered divs to the left and all even numbered divs to the right. Behold the <a href="/files/textcolumns/textcolumns.html" data-no-instant>huge gap</a> on the left side. I was stumbled. IE displayed it like I thought it worked, Firefox and Opera both displayed the gap (note to self: it's seldom a bug if both Fx and Op display it the same).</p>
<p>So, where does the gap come from? I went looking in the <a href="http://www.w3.org/TR/CSS21/visuren.html#float-position">CSS specification on float positioning</a> and found an interesting list of the rules that govern floats. As with almost all specifications they are not meant to be easy to read, so made a version of them where I use some sample code to explain each of the rules.</p>
<p>This is the sample code you need to have in mind:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"parent"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"child"</span><span class="p">></span>...<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"child2"</span><span class="p">></span>...<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">child</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">#</span><span class="nn">child2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<ol>
<li>#child and #child2 must stay to the right of #parent's left border.</li>
<li>#child2 must be to the right of #child since #child is earlier in the source. If there is not enough space to the right of #child, #child2 must be moved below #child instead.</li>
<li>If #child2 was floated right and #child and #child2 could not be fitted on the same line, they still must not overlap.</li>
<li>#child and #child2 must stay below #parent's top border.</li>
<li>#child2's top border may not be higher than #child's top.</li>
<li>If #child was display: inline; #child2 must still not be above it.</li>
<li>With #child and #child2 both floated left on the same line, #child2 may not stick out outside of #parent's right edge, unless it is already as far to the left as possible.</li>
<li>#child and #child2 must be placed as high as possible</li>
<li>#child and #child2 must be placed as far to the left as possible.</li>
</ol>
<p>The tricky one here is rule 5. It means that if #child was moved down for some reason, #child2 will have to move down too. Check <a href="/files/textcolumns/textcolumns.html" data-no-instant>the example again</a>. See the space above box5 and compare it to the top of box4. Box5 can't be above box4 according to rule 5 above. This is clearly what's going on here. If we made box2 smaller than box1 there would be a space above it by the same reason.</p>
<p>Note that the list of rules is a prioritized list; rules earlier in the list are more important than the latter ones. To Internet Explorer, rule 8 seems to be more important than rule 5. Strange move by IE.</p>
<p>I hope this gave you an "Aha!" feeling, it certainly gave me.</p>
Challenge: Marking up the world cup2006-07-03T23:25:37+02:002006-07-03T23:25:37+02:00http://friendlybit.com/css/challenge-marking-up-the-world-cup/Emil StenströmIt's at the end of the world cup and it's everywhere (fotball for those that live in a cave :). It might be that I spend too much time with thinking about...
<p>It's at the end of the world cup and it's everywhere (<em>fotball</em> for those that live in a cave :). It might be that I spend too much time with thinking about the web but I got this little markup issue on my mind. I'm not entirely sure how I would solve it but I have some ideas.</p>
<p>How would you mark up the FIFA World cup 2006 <a href="http://en.wikipedia.org/wiki/2006_FIFA_World_Cup#Bracket">single elimination bracket</a>? If you don't know what it is, have a look at the page linked to. It's basically 16 teams that play against eachother, one to one so half of the teams get kicked out in each step. Next step is with 8 teams, 4 teams ans so on. Pretty straight forward.</p>
<p>Now. Say you got contacted by FIFA to make that chart to put up on the web. Very skilled in Web Standards like you are, you start to think about what kind of data this really is. Is it a list? Ordered, unordered, nested? Is it a table, with the rounds as headers? Is it perhaps a definition list, mapping games played to teams? I don't have any 100% true answers, I'm hoping for your help there.</p>
<p>The second problem is of course the style. What methods would you use? There's quite a lot of boxes to place. Percentages? Can you make it zoom well?</p>
<p>Pasting code in comments to this blog is a bad idea (they just get messed up), so put it up on your own site instead an link to it by leaving a comment. Add a little explaination of your thinking of you wish. Can you do it?</p>
<p><strong>Update:</strong> Here's my suggestion of <a href="/files/worldcup/worldcup_bracket.html" data-no-instant>markup and CSS for the world cup bracket</a>.</p>
Current issues with Microformats2006-07-01T17:52:06+02:002006-07-01T17:52:06+02:00http://friendlybit.com/html/current-issues-with-microformats/Emil StenströmA couple of weeks ago I attended Geek Meet in Stockholm. It's a small group of people gathering to talk about semantics and share their knowledge of...
<p>A couple of weeks ago I attended <a href="http://www.robertnyman.com/geekmeet">Geek Meet</a> in Stockholm. It's a small group of people gathering to talk about semantics and share their knowledge of front-end webdev. It was the second meet and, just like on the last one, I had a great time. It's something special meeting up with people that share your interest for the small niche front-end web development is.</p>
<p>On that meeting <a href="http://www.peterkrantz.com/">Peter Krantz</a> held a presentation about microformats, a way to standardize small snippets of HTML you use often. What was different with the presentation is that it wasn't just praise like many new techniques get. The presentation showed both the good and bad sides, and didn’t close with a final conclusion of whether it should be used or not. This article is my view of microformats (and includes some of the issues from Peter’s presentation).</p>
<h2 id="what-are-microformats">What are microformats?<a href="#what-are-microformats">#</a></h2>
<p>Microformats are small standardized snippets of HTML. They are standardized to make it easier for crawlers/robots to find certain types of information. One idea could be to make contact information easier to find for a robot and letting anyone build a directory out of this information. Browsers could support this and display information in some special way. Sounds like a pretty good idea to start with, doesn't it?</p>
<p>Microformats are not restricted to contact information, hCards. There's also hCalendar for description of events, hReview for reviews of things and so on. You'll find the full list on the <a href="http://microformats.org/wiki/Main_Page">microformats wiki</a>.</p>
<p>An example of a hCard:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"vcard"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">"url fn"</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://tantek.com/"</span><span class="p">></span>Tantek Çelik<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"org"</span><span class="p">></span>Technorati<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<h2 id="serious-problems-with-the-format">Serious problems with the format<a href="#serious-problems-with-the-format">#</a></h2>
<p>Microformats are not perfect. The first problem is that they don't use namespaces. Namespaces are some way of describing what you mean with a word and in this case it applies to the class name of the formats. Check the example above. If you wrote a robot, how would you recognise an hCard? The only information available is the class name of the above. This means you would need to search each page for that class name. This is quite inefficient from a parser’s point of view.</p>
<p>What's worse, this means no one can use the class name "vcard" on their pages, that would make the robots get faulty information. Even this post probably breaks a few parsers because the code example above looks pretty much like an hCard. I hear the counter argument, "but no one uses vcard as a class name if they don't use it for that", I can only tell you I just did.</p>
<p>Multiplying the damage of not using namespaces is versioning. Compare with HTML, where in early versions of HTML a <a href="http://hsivonen.iki.fi/doctype/">Doctype</a> was not needed. Then the authors decided that the format needed an update, and with the update new elements were added. Without a doctype the browsers couldn't tell the difference between the formats and the doctype was added in. This is exactly what will happen with hCard (or any other microformat that doesn't use namespaces) if needs to get updated.</p>
<p>Is versioning a problem? Not if the format is perfect from the start, without any kinds of problems that need to be fixed in future releases. You see where this is going right?</p>
<p>Except for the issue with namespaces and parsing of class names we also have dates. Dates with time included are in the hCalendar format marked up with the abbr element. It looks something like this:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">abbr</span> <span class="na">class</span><span class="o">=</span><span class="s">"dtstart"</span> <span class="na">title</span><span class="o">=</span><span class="s">"20060621T1030-0700"</span><span class="p">></span>21 june 10:30<span class="p"></</span><span class="nt">abbr</span><span class="p">></span>
</pre></div>
<p>Is the title attribute used correctly here? I think not. The abbr element is meant to give users that do not know what a certain term/expression stands for a short explaination. In the example above it's not easy guessing that "T" stands for time and that the number afterwards is a notation of time zone (GMT-7 or PDT-7?). All of this is of course possible to read from the ISO specification, but people hovering your link will not do that. The title attribute on abbr elements should be humanly readable!</p>
<p>If you still don't agree with that you can check out ISOs own text about ISO 8601. Under "Advantages of ISO 8601" you can see:</p>
<ul>
<li>Easily readable and writeable by systems</li>
<li>Easily comparable and sortable</li>
<li>Language independent</li>
<li>Larger units are written in front of smaller units</li>
<li>For most representations the notation is short and of constant length</li>
</ul>
<p>While all of those are good points, none of them have anything to do with being easy to read for a human. This is the very point of the title attribute of the abbr element. For the sake of discussion Tantek wrote about the <a href="http://tantek.com/log/2005/01.html#d26t0100" title="Reasons behind choosing ISO 8601 for microformats">choice of ISO 8601</a> when the use of title was included.</p>
<h2 id="improving-the-format">Improving the format<a href="#improving-the-format">#</a></h2>
<p>The idea of making it easier for robots to parse pages is a good idea, but I'm not sure embedding content for robots into the human content is the best solution. What about putting this information into your <a href="/feed/" title="Friendlybit's web feed">web feed</a> instead? Feeds are made to be readable by robots and since they are xml they can easily be expanded with new types of data.</p>
<p>If I were to consider microformats I would like the two main issues above to be fixed first. <em>Add some kind of namespaces to the formats</em> and make them required. One idea would be to use a meta element for each format you want to use inside the document. The name is the format you use, the content is what version you are using, and the scheme is a link to the <a href="http://microformats.org/wiki/xmdp-brainstorming">microformat profile</a> that corresponds to that format. Note that the use of this element should be required, not optional.</p>
<p>It would look something like this (you can of course use several formats by repeating the meta element):</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">"hCard"</span> <span class="na">content</span><span class="o">=</span><span class="s">"1.0"</span> <span class="na">scheme</span><span class="o">=</span><span class="s">"http://www.w3.org/2006/03/hcard"</span><span class="p">></span>
</pre></div>
<p>The second improvement would be to <em>use something else than the title attribute for the dates</em>. Titles should be used for human readable content, not machine readable so that needs to change. Switching to another format for dates seems like a bad idea since ISO 8601 is so widely spread. So, what to do? I'm not sure. My best bet would be to use the class attribute like most of the microformats are built up on. The dates do not have a space in them so they can be parsed just like other class names.</p>
<h2 id="conclusion">Conclusion<a href="#conclusion">#</a></h2>
<p>Even though microformats are basically trying to make it easier to parse the web (an idea I like) I'm not sure this is the right way of doing it. Human and robot content are most often different things and mixing those in the same document could mean you end up with a mess. I have not touched upon all the extra divs and spans microformats add to the code but that's also a sign that we're moving the wrong way.</p>
<p>If the authors of microformats want their formats to spread they need to fix the two issues above. The two suggestions of improvement I made above would make me consider using them. Right now I don't feel it’s worth it.</p>
Reminder: Cross browser font sizes2006-06-30T18:15:09+02:002006-06-30T18:15:09+02:00http://friendlybit.com/css/reminder-cross-browser-font-sizes/Emil StenströmI'm sure most of you have already read the excellent experiment on font sizes but it's important enough to summarice here. The problem is how to make as...
<p>I'm sure most of you have already read the <a href="http://www.thenoodleincident.com/tutorials/box_lesson/font/index.html" title="Noodleincidents guide on font sizes">excellent experiment</a> on font sizes but it's important enough to summarice here.</p>
<p>The problem is how to make as many browsers as possible display fonts in the same size, without using pixels or other absolute units. Why shouldn't you use fixed font sizes? Because they make Internet Explorer unable to zoom the text with text-zoom, something that's bad for accessibility.</p>
<p>When you start experimenting with this problem you quickly get into problems. I tested in Firefox 1.5, Internet Explorer 6 and Opera 9 and it was incredibly hard (Want a challange? Don't read on, try it by yourself) even with just those few browsers. Opera has problems with units it seems. If you use em:s you can't use more than two decimals, Opera will round it them differently than the others.</p>
<p>Anyway, Owen Briggs solved this for us in a very simple way:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="c">/* Set the size in percent on the body */</span>
<span class="nt">body</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mi">76</span><span class="kt">%</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="c">/* All other sizes should be in em units with maximum of one decimal */</span>
<span class="nt">p</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">em</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="nt">h1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="kt">em</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="nt">h2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mf">1.8</span><span class="kt">em</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>From my simple tests it seems to work fine. Did you know?</p>
Feeling the Digg effect2006-06-30T12:57:25+02:002006-06-30T12:57:25+02:00http://friendlybit.com/other/feeling-the-digg-effect/Emil StenströmHi people! I just wanted to say I'm sorry for the downtime/slowness recently. My post Real hackers don't use CSS got digged which meant I got LOTS of...
<p>Hi people! I just wanted to say I'm sorry for the downtime/slowness recently. My post Real hackers don't use CSS got digged which meant I got LOTS of traffic. Fortunately I got some help first .htaccess redirecting digg traffic to duggmirror (they save digged posts automatically). That took the pressure down enough so I could install WP-Cache and get it configured. Now the site is back up again and is probably also faster for all of you.</p>
<p>Thanks for sticking to this site, I love you all! (lot's of good articles on the way, stay tuned)</p>
<p>(A note: I use <a href="http://www.stacken.kth.se/">stacken</a> as my host and it was not their fault the server got slow; wordpress just uses up too many mysql connections and a proper cache fixes that.)</p>
Beyond the web with CSS: PrinceXML and S52006-06-25T00:37:34+02:002006-06-25T00:37:34+02:00http://friendlybit.com/css/beyond-the-web-with-css-princexml-and-s5/Emil StenströmRight now, depending on what kind of presentation you will be doing, you use different techniques. I'm not talking about "presentation" as in design here,...
<p>Right now, depending on what kind of presentation you will be doing, you use different techniques. I'm not talking about "presentation" as in design here, I'm talking about web sites, printed paper, slide shows and so on, different types of media. How many of you use the print feature in browsers for your reports? Didn't think so.</p>
<p>Wouldn't it be nice if there was only one set of standards you needed to learn? One set that worked for all kinds of documents. One where encoding problems of differences in alphabets had been solved. One with a huge community of developers that gave of their time to help you with problems. Wouldn't that be nice? Good thing that set of standards exist: HTML and CSS.</p>
<h2 id="printing-like-it-once-was-word-and-latex">Printing like it once was: Word and LaTeX<a href="#printing-like-it-once-was-word-and-latex">#</a></h2>
<p>The ordinary Windows user uses <a href="http://office.microsoft.com/word">Mircosoft Word</a> for editing text. Word is popular for its ease of use and hides all the code from the user, instead showing the document like it will be printed. This of course pushes the filesizes up because of inefficient code, just like with any <acronym title="What you see is what you get">WYSIWYG</acronym> editor. Word supports the separation of structure and design by it's templates but hides this feature behind menu selections instead of promoting it as the preferred method. It also uses a proprietary format for storing the documents, something that makes sharing documents harder. Word costs a lot, but if you're lucky it's included when you buy your Windows machine.</p>
<p>For scientific work, <a href="http://www.latex-project.org/">LaTeX</a> is very popular. LaTeX takes a very different approach from Word at editing text by requiring the user to mark up structure with its own markup format. It comes with a few predefined designs that you pick among by writing some markup in the beginning of the document. The document is then compiled by a command line program into an intermediary format that can be sent to a printer. If you know what you're doing, this makes it easy to get those default designs out fast. The problem with LaTeX is when you <em>do</em> want to change the design. This requires you to dig deep into TeX syntax, a language not known for its ease of use.</p>
<p>Example of some LaTeX code:</p>
<div class="highlight" data-language="LATEX"><pre><span></span><span class="k">\\</span>documentclass<span class="nb">{</span>article<span class="nb">}</span>
<span class="k">\\</span>title<span class="nb">{</span>Cartesian closed categories and the price of eggs<span class="nb">}</span>
<span class="k">\\</span>author<span class="nb">{</span>Jane Doe<span class="nb">}</span>
<span class="k">\\</span>date<span class="nb">{</span>September 1994<span class="nb">}</span>
<span class="k">\\</span>begin<span class="nb">{</span>document<span class="nb">}</span>
<span class="k">\\</span>maketitle
Hello world!
<span class="k">\\</span>end<span class="nb">{</span>document<span class="nb">}</span>
</pre></div>
<h2 id="printing-with-web-standards-princexml">Printing with web standards: PrinceXML<a href="#printing-with-web-standards-princexml">#</a></h2>
<p>The runner up in the print category is <a href="http://princexml.com/">PrinceXML</a>. It's based on ordinary (X)HTML/XML together with CSS and outputs PDF documents ready for printing. The CSS support is quite remarkable, managing to render the <a href="http://webstandards.org/action/acid2/">Acid2 test</a> according to standard and supporting new CSS3 features like cross-references without problem. The handling of page sizes, page footers and headers comes from the <a href="http://www.w3.org/TR/css3-page/">CSS3 Paged Media</a> module and too works well from my testing.</p>
<p>Below you can see an example of what can be done in PrinceXML. First we add a counter that keeps track of what number each block with the classname figure as. Then we add that number before the figure's caption. Lastly we add a parantesis with the figure number too all links that link to a certain figure.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">.</span><span class="nc">figure</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">counter-increment</span><span class="p">:</span><span class="w"> </span><span class="n">fig</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">figure</span><span class="w"> </span><span class="p">.</span><span class="nc">caption</span><span class="p">::</span><span class="nd">before</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">content</span><span class="p">:</span><span class="w"> </span><span class="s2">"Figure #"</span><span class="w"> </span><span class="nb">counter</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span><span class="w"> </span><span class="s2">": "</span>
<span class="p">}</span>
<span class="nt">a</span><span class="o">[</span><span class="nt">href</span><span class="o">^=</span><span class="s2">"#fig_"</span><span class="o">]</span><span class="p">::</span><span class="nd">after</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">content</span><span class="p">:</span><span class="w"> </span><span class="s2">" (see figure "</span><span class="w"> </span><span class="nf">target-counter</span><span class="p">(</span><span class="nb">attr</span><span class="p">(</span><span class="n">href</span><span class="p">),</span><span class="w"> </span><span class="n">fig</span><span class="p">)</span><span class="w"> </span><span class="s2">")"</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>I am currently using the program for my degree thesis, a 34 page giant that has quite strict rules it needs to follow for styling. PrinceXML handles things just like it should. It costs a bit, but if you write a lot of documents it's probably worth it. If you can handle a promotional first page a <a href="http://princexml.com/download/">free trial version</a> is available on the web site.</p>
<h2 id="slide-shows-like-they-once-were-powerpoint">Slide shows like they once were: PowerPoint<a href="#slide-shows-like-they-once-were-powerpoint">#</a></h2>
<p>Microsoft is in the lead in the slide show area too with its well known <a href="http://office.microsoft.com/powerpoint">Microsoft PowerPoint</a>. Interestingly PowerPoint goes a long way towards separation with it's easy to use layout modes. You pick a layout from a easy to overview list of options and then just click and type to fill it with your content. What isn't included is design. Much like LaTeX, PowerPoint lets you pick from a number of premade templates but makes it hard to make your own. Given that ease of use is more important for PowerPoint than customization you could say that the product is successful. For someone like me though, that wants to make my own designs, learning how to make PowerPoint templates isn't easy enough to be interesting. PowerPoint also uses a proprietary format and costs <em>mucho dinero</em>, but if you are lucky it was included when you bought your computer.</p>
<h2 id="slide-shows-with-web-standards-s5">Slide shows with web standards: S5<a href="#slide-shows-with-web-standards-s5">#</a></h2>
<p>Eric Meyer is the author of a web standards based <a href="http://meyerweb.com/eric/tools/s5/">slide show system called S5</a>. It's rather easy to use for someone used to HTML and CSS. Pick your favourite properly marked up HTML file, add <code><div class="slide"></code> around a block of content you want on its own slide, link some javascript and CSS and you're ready to go. The slide show is then run in a web browser in fullscreen mode. It supports incremental display and resizes with the browser window, just like PowerPoint. It's also completly free.</p>
<h2 id="summary">Summary<a href="#summary">#</a></h2>
<p>It <em>is</em> possible to use HTML and CSS for both web, print and slide shows. In fact you can combine all of them and by using the media attribute on your link elements. That way the same document can be shown on the web, be rendered as a PDF in PrinceXML and displayed in a slideshow with S5.</p>
<p>Isn't this standards stuff quite fantastic?</p>
Real hackers don’t use CSS2006-06-11T15:15:58+02:002006-06-11T15:15:58+02:00http://friendlybit.com/css/real-hackers-dont-use-css/Emil StenströmBack in the old days of 1996 there were two kinds of people. Those who understood the web, often referred to as "hackers", and those that didn't. A hacker...
<p class="first">
Back in the old days of 1996 there were two kinds of people. Those who understood the web, often referred to as "hackers", and those that didn't. A <em>hacker</em> could throw together a website in a few minutes, filled with the latest possibilities that the web offered: animated gifs, scrolling marquee text and blinking red text for the really important stuff. It was a glorious time and the hackers really ruled the web. It started growing.
</p>
<h2 id="hackers-and-designers">Hackers and designers<a href="#hackers-and-designers">#</a></h2>
<p>With growth came the <em>designers</em>. They wanted to use the web just like the unlimited piece of paper it was. So they sent their designs, the same designs they had previously printed, to the hackers and said: "I want this on the web". The hackers looked at the designs and didn't like them at all. But the designers were the ones paying their salaries so they had no chance but to do what the designers wanted.</p>
<p>When the hackers started working they quickly came to the conclusion that this was harder than they had predicted. Then a smart guy that really knew his way around the web found a tutorial describing how to do something called "image maps". The hackers cheered! They could take the dreaded designs and put them up on the web as images. Then add transparent clickable areas on top of the images that linked to other images. The hackers' status had been reinstated and the designers looked at the results and were happy, "It looks just like we want" they said.</p>
<h3 id="how-to-make-a-website-a-hackers-guide">How to make a website, a hacker’s guide:<a href="#how-to-make-a-website-a-hackers-guide">#</a></h3>
<ol>
<li>Convert the designers images to JPG</li>
<li>Add an image-map to each one of them</li>
<li>Make sure all links work</li>
<li>Show the designers</li>
</ol>
<h2 id="hackers-and-customers">Hackers and customers<a href="#hackers-and-customers">#</a></h2>
<p>Here entered the <em>customers</em>. The company website, that looked just like the designers wanted and was coded just like the hackers wanted, was very slow. Sometimes it took over 15 minutes for the customers to get the info they wanted from the site. Phones started ringing in the hackers' offices and they all gathered to try to solve the problem. This was when the major breakthrough in the web history came.</p>
<p>One clever hacker suggested that they split the images in many parts and used tables to put them back together. The older hackers scratched their heads, "Tables? Where did they hear of them before?”. After some research they found that tables were sometimes used in research reports to show a grid of values. “Just put some images in those cells instead and it will look just like before”, explained the clever hacker. He continued, "… but that doesn't make anything faster. To make the page faster we split it so that we can remove some parts. If there is a large block of blue somewhere we can remove that image and set a background-color on the cell instead!". There was much rejoice and the hackers got to work. Many had problems dealing with splitting the images in the image programs, but after a couple of weeks of training they mastered it.</p>
<p>The years passed by and the hackers got better and better at taming tables to do just want they wanted. Someone came with the idea of putting another table inside the first one. That made the code a little easier to maintain since they didn't require the use of row- and colspan. Additionally that made it possible to add margins to your text, something that made the designers happy. Someone came with the clever suggestion that sometimes text can be removed from the image and written in the cell instead. This made the designers a bit annoyed since sometimes the customers got the wrong font but it wasn't an issue big enough to start a fight over.</p>
<h3 id="how-to-make-a-website-a-hackers-guide-emversi">How to make a website, a hacker’s guide (<em>version 2</em>):<a href="#how-to-make-a-website-a-hackers-guide-emversi">#</a></h3>
<ol>
<li>Convert the designers images to JPG</li>
<li>Slice the images so that the big one-colored areas can be replaced with a table cell</li>
<li>See if any of the text can be removed from the image and set in a cell</li>
<li>Link each individual image correctly or use an image-map.</li>
<li>Make sure all links work</li>
<li>Show the designers</li>
<li>Show the customers</li>
</ol>
<h2 id="hackers-and-standardists">Hackers and standardists<a href="#hackers-and-standardists">#</a></h2>
<p>The earth shook and the <em>web standardists</em> entered the scene. The standardists said to the hackers, "You are doing things all wrong, you need to redo your sites and learn everything from scratch again". The hackers laughed. Their customers were happy, the designers were happy, they were happy, why should they change? The standardists spoke again, "but your page will load faster with standards". The hackers looked back and remembered how slow their sites once were, they looked at the adoption of high speed internet connections and they reckoned that speed wasn't a problem.</p>
<p>The standardists were now annoyed, why couldn't the hackers understand why standards were better? They gave it one last chance and said "But if you use CSS for layout your sites will be much easier to maintain!". In reply the hackers showed all their table skills they had acquired over the years. One guy had 16 nested tables to show. Another guy used frames to layout his site and had a whopping 25 frames in a spectacular pattern which all the other hackers envied. The hackers really knew what they were doing. They said, "There’s no need learning this new stuff, it will just take a lot of my time and it isn't any better".</p>
<h3 id="how-to-make-a-website-a-standardists-guide">How to make a website, a standardist’s guide:<a href="#how-to-make-a-website-a-standardists-guide">#</a></h3>
<ol>
<li>Look at the design the designer gave you, figure out what parts the design consists of.</li>
<li>Start writing the HTML corresponding to those parts. Try to avoid adding elements to the HTML just for the sake of design. Make sure all content in the design is represented in the HTML (text preferable).</li>
<li>Link a CSS file to your HTML and start adding style to the document. Test in the modern browsers and read guides with common bugs to fix problems you encounter.</li>
<li>Show the designers and explain why they can't have it look just like it would on paper.</li>
<li>Do user testing to determine things work or not.</li>
<li>Release it to the customers and be open to feedback.</li>
</ol>
<h2 id="conclusion">Conclusion<a href="#conclusion">#</a></h2>
<p>When you, as a standardist, talk to hackers about standards, keep in mind that they are good at what they do. There's a reason they are doing it a certain way and it works. Just throwing out a "Tables are so -96" won't bite; you need to be smarter than that. Don’t forget that you were once in the same seat, and use the same arguments that made you switch.</p>
<p class="first">
And yes, that guy using frames for layout in the text above, was me.
</p>
Concept: Four layers of web development2006-06-03T18:45:07+02:002006-06-03T18:45:07+02:00http://friendlybit.com/css/concept-four-tier-web-development/Emil StenströmWhen thinking about web development on the client side, I tend to think of four different layers. Any (well built) framework will cater for all of these...
<p>When thinking about web development on the client side, I tend to think of four different layers. Any (well built) framework will cater for all of these layers and all good developers will be aware of them. The layers I'm thinking about are: Data, Structure, Design, and Behavior. This article discusses all four of those and explains how they relate.</p>
<h2 id="data-layer">Data layer<a href="#data-layer">#</a></h2>
<p>The data layer is the most important one and strangely the one most people get confused about. HTML is <em>not</em> the data layer, the <strong>content</strong> is. The data layer is the raw data that you are presenting, the text, the images, the sound, the video, whatever content you want to serve. For bigger sites the data is often stored in a database or perhaps XML files somewhere and then processed server side every time someone wants to access it.</p>
<p>This layer is also where all websites should start. What content do you have? If the content is bad no pretty design or fancy Web 2.0 technique is going to cater for that. In fact, content together with bad uses of the other layers, <a href="http://www.andyrutledge.com/bad-design.php">might still work</a>!</p>
<p>One last point to make about data is that you should make sure to use the best possible media for representing your content. If it can be text, use text! Don't use images for text, narrate your podcasts (or at least provide a text-summary), put your videos online with descriptions to them. Having that text there helps you convey your point, search engines will find you, your users will be able to skim read while it loads and disabled users will get access to at least some of your content.</p>
<h2 id="structural-layer">Structural layer<a href="#structural-layer">#</a></h2>
<p>The structural layer is where the much misunderstood HTML comes to play. HTML's job is to take the data it has received from the data layer and <a href="/html/datatypes-of-html/" title="Some examples of data structures you have available in HTML">add some structure to it</a>. Mark up what parts are headers, make sure lists get the HTML that best describes them, split the page up in the important parts and so on.</p>
<p>HTML also adds some semantics to the data but since it's quite a limited dictionary we have to work with I believe this is secondary. If you happened to have the kind of data that HTML happens to catch with its elements be sure to use them, if not make sure you at least capture the structure of it.</p>
<p>You know you have done this level right if your site works with nothing but data and structure.</p>
<h2 id="design-layer">Design layer<a href="#design-layer">#</a></h2>
<p>The design layer is where you define the looks of your data. Design requires a good basic structure to be useful. On the web you should use CSS for this layer, a language that has been built upon the idea of a solid structure and is remarkably powerful. As you know CSS targets certain elements and then defines their look. Without a solid structure this is not possible.</p>
<p>Good designers often point out that only working with the looks of a site will not accomplish good design. They also work on the structural layer by making sure structurally important content gets the most exposure in the design. This is also strengthens the idea that structure is a layer upon which design works.</p>
<h2 id="behavioral-layer">Behavioral layer<a href="#behavioral-layer">#</a></h2>
<p>Behavior is the last layer I'm going to talk about. It's the one that's least important; data, structure and design are all more effective in conveying your message. None the less, added behavioral functionality <em>can</em> be powerful if executed properly on top of the other layers.</p>
<p>Javascript is the most used language for adding new behavior to websites. With the whole <a href="http://en.wikipedia.org/wiki/Web_2.0">Web 2.0</a> and <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29">AJAX</a> wave we are experiencing many new sites that adds a behavioral layer without even thinking about it. We should be careful; becoming dependent on the new behavior (the site not working without it) means you will lose many potential visitors, the most important single one being search engines. Behavior should always be added separately and only enhance the experience for those that has it enabled. This is what's called unobtrusive javascript.</p>
<h2 id="putting-it-all-together-four-tier-web-development">Putting it all together: four tier web development<a href="#putting-it-all-together-four-tier-web-development">#</a></h2>
<p>Putting all these four parts together we get the following:</p>
<p><img src="/files/four-tier-webdev.png" alt="Adding layers step by step to a paragraph of text" /></p>
<p>Is this the same mental model you use? Let me know through comments.</p>
<p><strong>Update:</strong> Threehouse has an image up showing the four layers in the context of javascript connection the layers together.</p>
Accepted to the 9rules network2006-06-03T22:50:28+02:002006-06-03T22:50:28+02:00http://friendlybit.com/other/accepted-to-the-9rules-network/Emil StenströmI just wanted to drop a note to everyone that I got accepted to the 9rules network. 9rules is a network for all kinds of quality content and you just need...
<p>I just wanted to drop a note to everyone that <a href="http://9rules.com/blog/2006/06/round-4-list/">I got accepted</a> to the <a href="http://9rules.com">9rules network</a>. 9rules is a network for all kinds of quality content and you just need to have a quick look at the members to see that they attract the right people. It will be very interesting to see what this leads to!</p>
<p>In other news my site was mentioned in the swedish magazine "Mobil" that covers everything about mobile phones (no article available online). They had an article about how to make a website for your phone and ended with a list links. In that list was my <a href="/css/beginners-guide-to-css-and-standards/">beginners guide</a> and the rest rest of the page was a gigantic screenshoot of my frontpage. Fun! :)</p>
<p>Traffic is also increasing again after people jumped on the "Knowledge levels of [Add your thing here]". Roger has a <a href="http://www.456bereastreet.com/archive/200606/web_knowledge_levels/">post about some levels of articles</a></p>
<p>Can you tell I'm happy? I AM! :)</p>
Inline CSS should not be allowed in strict doctypes2006-05-28T22:48:10+02:002006-05-28T22:48:10+02:00http://friendlybit.com/css/inline-css-should-not-be-allowed-in-strict-doctypes/Emil StenströmAs many of my readers already know all pages should include a doctype. The doctype tells the browser (or other user agent) what kind of document it can...
<p class="first">
As many of my readers already know all pages should include a doctype. The doctype tells the browser (or other user agent) what kind of document it can expect and what standards it follows.
</p>
<p>You can divide doctypes into two categories. The first category consist of the <em>transitional</em> ones, the ones that allow old syntax and still validate, and the other one consist of the strict ones. I have repeatedly <a href="/css/cross-browser-strategies-for-css/#mode">recommended the strict versions</a> for a simple reason: it's the best ones for separating design from content.</p>
<p>Just to show an example, transitional allows the following:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">body</span> <span class="na">bgcolor</span><span class="o">=</span><span class="s">"blue"</span><span class="p">></span>
<span class="p"><</span><span class="nt">center</span><span class="p">></span>
</pre></div>
</div><p>Strict, by its very nature, requires the use of CSS instead.</p>
<p>What I find strange is that <em>inline CSS</em> is valid in strict. Inline CSS is when you use the <code>style</code> attribute to set design information inside of the HTML. As an example the two deprecated pieces of code above can be done with:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">body</span> <span class="na">style</span><span class="o">=</span><span class="s">"background: blue"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-align: center"</span><span class="p">></span>
</pre></div>
</div><p>How is that any better than the transitional versions? Inline CSS goes against all the logic involved in the idea of two distinct doctypes. Why should you want to include design information inside of a document that you just explicitly stated would separate the two?</p>
<p>I hear the obvious reply: "What if I load design info from a database? I need to use inline CSS then!". To me, that sounds like a perfect case where you need to go <em>transitional</em>, if you can't manage to separate the two - don't.</p>
<p>Strict doctypes are for documents where the webmaster has taken the time to clearly separate the content from the design, not other hybrids.</p>
Improving the web; Blogging, Google and Web standards2006-05-20T00:12:31+02:002006-05-20T00:12:31+02:00http://friendlybit.com/css/improving-the-web/Emil StenströmThe web has really changed the way we do things. Remember those paper timetables? No need for them anymore, we simply type in our destination on a box and...
<p>The web has really changed the way we do things. Remember those paper timetables? No need for them anymore, we simply type in our destination on a box and get a step by step guide for what to do. Finding recipies? No need to look through books any more, just type in a few ingredients on your favourite food site. The examples are countless but there is no time for us to sit back and relax just yet. The web <em>can</em> be improved. We can get more people to publish their stuff online, we can get better tools for finding relevant info, and we can make the information accessible to more people. In this article I'm going to talk a little about each of those three points.</p>
<h2 id="we-need-more-information">We need more information<a href="#we-need-more-information">#</a></h2>
<p>We need more information. People will argue and say "No, there's enough junk online already" but I don't care. More information is a good thing. The web is currently not a good representation of the world at large. The is a million technology weblogs and five about shoemaking. Another million sites about how it's like to be a teenager today and another five about life as an 80 year old. You know what I'm getting at? We need a wider variety of people on the web, not only people that are just like us.</p>
<p>Another thing to remember is that text only is one facet of information. With today’s bandwidth available we can look at live video from all over the world. We can listen to live radio and music just as easy as we read the web. We then have a look at availability. I'd say that at most one out of 1000 people publishing on the web is using something else than text (This site is no exception). I know that there are people out there that have a video camera, that have a microphone, and know how to put it up on the web. But they don't.</p>
<p>This lack of variety in information is a real problem. It builds barriers towards people we just don't know anything about and it fools us surfers to believe the world is smaller than it seems. "No, there can't be any problems with the Chinese government, we would have heard about it!” or what about "Christianity must be the biggest religion, just look at what people are writing most about".</p>
<p>There <em>are</em> ways the tackle this problem and the concept of blogging is one of them. It makes it easy to almost anyone, anywhere to just start writing in a few minutes. You can be anonymous, you don't have to tell the truth, there's no age check and it doesn't cost you money. This opens up to real diversity on the web. The technology exists, what we need to do is get people online and make them use it. So tell your friends to pick something they love or hate and blog about it. We need more information.</p>
<h2 id="we-need-relevant-information">We need relevant information<a href="#we-need-relevant-information">#</a></h2>
<p>The next step, after we have gotten a larger and more diversified web, is to start filtering it. I'm not talking censoring here, I mean filtering in the sense to "filter what you want". This can be tied to a certain task you want to accomplish or it can be a strong interest of yours that you want to follow. It doesn't matter which, what matters is that there are ways to easily find relevant information.</p>
<p>There are many ways of determining relevancy on the web and the one most successful is linking. Links are like recommendations; anyone that links to a site is telling their readers a certain site is recommended. It's relevant for the subject at hand and it contains good information. If you are just looking for random information about something looking at a few links might be enough. For example, if <a href="http://www.456bereastreet.com">Roger Johansson</a> links to something web related I can be pretty sure it's good.</p>
<p>For more task oriented queries we need something else. If someone is looking for a plane ticket they will probably not know who the authority in that area is. Google is the search engine that has had the greatest success with solving this problem and the solution is simple. Gather the recommendations for as many sites as possible and reply to queries with what <em>most</em> people recommend. Just think about it, if 100 people recommend FlyPlane and 1000 people AirFlight, who would you go for?</p>
<p>In reality it isn’t that simple, but in essence that’s how search engines work. Something that is important to note is that the system encourages people to write <em>good content</em>. Why is that? Simply because good content gets linked to, and more links means it's probably more relevant. This way Google and all the others are actively encouraging people to improve the web. Good, isn't it?</p>
<h2 id="making-information-accessible">Making information accessible<a href="#making-information-accessible">#</a></h2>
<p>So, we have lots of information from all over the world and we have the tools to find the most relevant info at any point. The last step is actually delivering the information to our users. This is where web standards come to play.</p>
<p>In the early nineties browser makers raced to get the coolest new features included in their browsers. The result was things like blinking text, different methods of representing "layers" and scrolling text. Web developers had a hard time keeping up with browser differences and often you had to construct two or more separate pages to send people to depending on what browser they used.</p>
<p>The W3C acknowledged this and presented a solution. Instead of browsers trying to find the coolest additions, let a standards organization handle the new additions. Let hundreds of people sit together and discuss new ideas long before they are implemented. When everyone has had a chance to say their meaning and problems has been eliminated you release a document presenting the new features together with implementation details. Now the browser makers can race over who supports the most recommended standards instead, and webmasters can just pick a set of standards that is well supported. One way of doing things instead of many incompatible ones.</p>
<p>Right now, the current recommendation is to use the strict versions of HTML of XHTML for structure, CSS for design and Javascript for behaviour. Using those standards means that your site is accessible by more than just the few browsers you have tested with. Both people and automated crawlers that that are after just your content can easily skip your design. People with old browsers will still be able to view your content, even though they don’t see the design the still get the content.</p>
<p>If you adopt the recommendations I mentioned above you have gotten quite far, but there is more. <em>Accessibility</em> is an area in web development that has gotten far too little exposure. It's focused on making it easier to people with various disabilities, varying from broken arms and color blindness to dyslexia. Previously people cared about old browsers, it’s time for a shift towards caring about people instead. Read up on accessibility, Mark Pilgrim's <a href="http://diveintoaccessibility.org/introduction.html">Dive into Accessibilty</a> is a good start.</p>
<h2 id="in-summary">In summary<a href="#in-summary">#</a></h2>
<p>I've gone over three areas where I believe there is space for improvement on the web.</p>
<ul>
<li>More diversified information. Get your friends on the web!</li>
<li>Better tools for filtering all the information depending on what we need. Build new and better tools for doing this!</li>
<li>Use web standards and care about accessibility. I try to help in this area with the help of this blog.</li>
</ul>
<p>Now I'm interested in your comments. What do you think? Are there more areas we need to look into?</p>
Language detection, a usability enhancer?2006-05-14T01:05:19+02:002006-05-14T01:05:19+02:00http://friendlybit.com/other/language-detection-a-usability-enhancer/Emil StenströmNatural language is by many considered something with very little structure. What many people don't know is that there are parts that are easily analysed....
<p>Natural language is by many considered something with very little structure. What many people don't know is that there are parts that are easily analysed. This article explains a simple but very effective algorithm for detecting what language a text are written in and continues to discuss possible applications.</p>
<p>More and more of the worlds population comes online and far from everyone want to write in English. In fact, most of the content online is not in English. This leads to the need for more tools that handle different languages; that translate, finds synonyms and so on. Different languages are important so we are going to need tools to handle that. This article handles the latin alphabet, simply becuase it's the only one I know. I'm sure you can apply the same ideas to other alphabets aswell.</p>
<h2 id="how-to-detect-language">How to detect language<a href="#how-to-detect-language">#</a></h2>
<p>When looking at the differences between languages you can find that they are many. Words, grammar, sentence length, number or syllables… we can go on forever. People skilled in both languages and algorithmics quickly found a very reliable way to tell languages apart: <em>Bigram statistics</em>. A bigram is just a pair of two letters like "xt" or "ty".</p>
<p>It turns out that bigram statistics for a text stays fairly constant (there's always few "tp" in English) and sometimes you don't need more than a sentence to determine the language. This is how the algorithm works:</p>
<ol>
<li><strong>Remove or translate characters</strong> you don't want to count. You might want to take into account special characters in different languages like É and Ü and decide how to handle them. Be sure not to remove the space character, it gives good statistics over with which letter words start and end.</li>
<li><strong>Split the text into bigrams</strong>. For this to work you need to take all bigrams in each word, that is, each letter is included twice. Example: "hello" contains "_h", "he", "el", "ll", "lo", "o_" ("_" means space). The more text, the more reliable the result will be.</li>
<li><strong>Count the occurrence</strong> of each bigram in a long list that contains all the bigrams.</li>
<li><strong>Calculate statistics</strong> over how often each bigram occurred.</li>
<li><strong>Compare</strong> with precalculated lists over different languages. You need to compile this list yourself but it's easy. Use <a href="http://www.google.com/advanced_search">Google Advanced Search</a> and set the language you want from there.</li>
<li><strong>Pick the language</strong> that has the most similar list.</li>
</ol>
<p>The only hard part to program is the comparing of two lists. For this we will use the <a href="http://en.wikipedia.org/wiki/Euclidean_distance">Euclidean distance</a> of the two lists of numbers. In essence, this is how Euclidean distance works:</p>
<ol>
<li><strong>Pick the values</strong> for the first bigram from the two lists you want to compare.</li>
<li><strong>Calculate the difference</strong> between the two values and <strong>square it</strong>.</li>
<li><strong>Repeat 1 and 2</strong> until you have one result for each bigram pair.</li>
<li><strong>Add all those results</strong> together and calculate the <strong>square root</strong> of that sum. You have your distance.</li>
</ol>
<p>Euclidean distance gives us a number. The lower the number the more like each other the two lists are. So we compare the calculated list with the precompiled lists for other languages and pick the language with the lowest number.</p>
<h2 id="real-world-applications">Real world applications<a href="#real-world-applications">#</a></h2>
<p>As you've see above detecting language isn't rocket science. Anyone with some solid programming skills could implement the algorithm above no matter what programming language. Anyone could also gather the statistics needed to make some bigram lists for different languages. So you could expect that this is used all over right? Wrong. A few examples:</p>
<p>Since my native language is Swedish I have downloaded an extra dictionary for Thunderbird to make it able to check both my Swedish and English e-mails for errors. It works well except for one thing. Since about half of the e-mails I send are in each of the languages, the dictionary is almost always set to the wrong one. Since the language is not shown anywhere I usually type a few words, think "what, isn't that correct?", and then remember that the wrong dictionary is selected. You can see where the language detection above would fit in right? They don't even need to see what I'm going to type; the language I will reply with will be the same as in the e-mail I'm answering to. That's usability.</p>
<p>Another example. Too few webmasters know about the <a href="http://www.w3.org/TR/html4/struct/dirlang.html#h-8.1">lang attribute</a>. It can be set on all HTML elements and specifies what language the content is in. The HTML 4 specification lists the following reasons to why you should use lang:</p>
<ul>
<li>Assisting search engines</li>
<li>Assisting speech synthesizers</li>
<li>Helping a user agent select glyph variants for high quality typography</li>
<li>Helping a user agent choose a set of quotation marks</li>
<li>Helping a user agent make decisions about hyphenation, ligatures, and spacing</li>
<li>Assisting spell checkers and grammar checkers</li>
</ul>
<p>It all boils down to: it's a good thing to say what language a page is written in. The problem is, not many know that the lang attribute even exists. Solution? Let the screen reader, browser, or search engine (they are doing it) auto-detect the language and act on it.</p>
<p>A third example is all those chat rooms. There are rooms all over the place and the topics range from poker strategies to horse equipment. What they all have are lots and lots of users and rooms where you can talk, in any language you want. Wouldn't it be nice if the chat software automatically detected which language was spoken in a room? Then you could see even before joining. Or even what languages a certain user speaks.</p>
<p>I'll call that the end of this article. It moved a bit outside of the webdev area but I hope you still liked it. Have any more ideas of where this could be useful? Want to show your javascript/python/ruby/etc implementation of it to me? Leave a comment.</p>
Emulating tables: Automatic width2006-05-07T01:59:50+02:002006-05-07T01:59:50+02:00http://friendlybit.com/css/emulating-tables-automatic-width/Emil StenströmMoving from tables to layouts based on CSS is a tough move for many. Things don't behave the way they use to and some effects are much harder to do with...
<p>Moving from tables to layouts based on CSS is a tough move for many. Things don't behave the way they use to and some effects are much harder to do with CSS. This article is about one of the tricks you might want when trying to get table-like effects using CSS: the dynamic width column, where you let the width be decided by an image. You may jump ahead and look at the <a href="/files/dynamic_left_column/" data-no-instant>dynamic width column</a> right away if you want.</p>
<h2 id="the-problem">The problem<a href="#the-problem">#</a></h2>
<p>What we are after is a way to emulate a simple effect when using tables. Look at this code:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">table</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/huvet_southpark.png"</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Some sample text here<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">table</span><span class="p">></span>
</pre></div>
</div><p>The code above will render two columns, and the width of the left one will be equal to the width of the image. This can be useful on a very dynamic site, where you don't know the width of the image and so you don't want to set it using CSS.</p>
<p>Looking at the code above you might see the problem though. Tables are for tabular data, and and image and some text are certainly not tabular. We need something better.</p>
<h2 id="the-solution">The solution<a href="#the-solution">#</a></h2>
<p>When you start to look at the problem you quickly realize that the image needs to be floated. There is just a few ways to put things side by side in CSS and floating is one of the few ways that works like we want it to. The image moves to the left and text flows around it. This looks all nice but if you add a border the other column you see that they are not really side by side. All that has happened is that the <em>text</em> has been moved to the left, not the container.</p>
<p>This can be solved by setting <code>overflow: auto;</code> on the right column. After setting this the container nicely contracts and sits where it should. IE6 doesn't play by the same rules though. Here you instead need to set <code>height: 1%;</code> to make it behave.</p>
<p>This final CSS looks like this:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">img</span><span class="p">#</span><span class="nn">cartoon</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">example</span><span class="w"> </span><span class="nt">div</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">overflow</span><span class="p">:</span><span class="w"> </span><span class="kc">auto</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="kc">auto</span><span class="w"> </span><span class="cp">!important</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p><strong>Update:</strong> After Rowan Lewis suggestion I now use <code>height: auto !important;</code> to send a correct height to modern browsers. IE6 does not understand <code>!important</code> and will therefore overwrite the height with the 1% value.</p>
<p>And the following HTML:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"example"</span><span class="p">></span>
<span class="p"><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/huvet_southpark.png"</span> <span class="na">id</span><span class="o">=</span><span class="s">"cartoon"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span><span class="p">></span>
Here's all the text
Even more text here!
Even more text here!
Even more text here!
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<p>Have a look at the example of the <a href="/files/dynamic_left_column/" data-no-instant>table-like behaviour</a>.</p>
Open letter to the IE Team2006-05-03T13:37:07+02:002006-05-03T13:37:07+02:00http://friendlybit.com/css/open-letter-to-the-ie-team/Emil StenströmDear IE Team, I have carefully followed the development of Internet Explorer 7 (IE7) and really liked what I've seen. Especially the CSS bugfixes are...
<p class="first">
Dear IE Team,
</p>
<p class="first">
I have carefully followed the development of Internet Explorer 7 (IE7) and really liked what I've seen. Especially the CSS bugfixes are wonderful, the tabs are really needed, and the team talking about the development on your blog is really nice too. You are doing a great job and you should receive credit for it.
</p>
<p>One thing keeps bugging me though. Soon you will release the browser on Windows Update and people will automatically start upgrading, replacing their old browser (IE6) with the new version. I use Windows Update so my version will be upgraded too, and there's the problem: I'm a web developer and I need to test my sites in more than one version of each browser. IE7's ability to <em>replace</em> IE6 instead of working standalone will for me be a pain. As I see it I have the following options:</p>
<ul>
<li><strong>Get another computer</strong>. On that other computer I could have the old version of IE installed, with security bugs and all, and then move from computer to computer while testing.</li>
<li><strong>Install a virtual machine</strong> on my current computer. This means I could have the old IE6 on the virtual machine and test there. While this sounds pretty good it still means I have a reserve a large part of my computer for IE6 testing, something that feels very strange to me. I looked up what Microsoft Virtual PC costs and found $129, an expence that a student can't take just like that</li>
<li><strong>Drop support for IE6</strong>. If you really could get all your current users to upgrade this would be a viable option. The problem is that you will not, at least for the comming five years. You will have the non-XP Windows users that won't get the oppurtunity to upgrade, you will have the modem users that will not have the bandwidth to upgrade and you will have the clueless people that will have no idea that there is an upgrade available. This is not a problem for you, because you are just working with the new version, but it is a problem for me as a web developer, because I have to deal with the old version for a long time still.</li>
<li><strong>Hack IE7 to work standalone</strong>. I have found some tutorials on how to make IE7 standalone but the problem with that is that it's a mess. Look at it, copying of registry entries, DLL files, and EXE files around. If this is what you want us to do, why not ship a nice and thoroughly tested version of this script yourselves?</li>
</ul>
<p>So, this is my dilemma. Which of the options do you want me to use?</p>
Datatypes of HTML; why HTML is great for structure2006-05-01T15:42:26+02:002006-05-01T15:42:26+02:00http://friendlybit.com/html/datatypes-of-html/Emil StenströmHTML is often bashed by people for being a bad language. People, often used to XML, talk about the lack of good elements for marking up things like authors...
<p class="first">
HTML is often bashed by people for being a bad language. People, often used to XML, talk about the lack of good elements for marking up things like authors and dates. While I agree that HTML would need a few more tags that help with marking the meaning of things I do think HTML is good at structure. This article is a attempt to show HTML's power by mapping how different datatypes in the common programming languages map to elements in HTML.
</p>
<ul>
<li><a href="#lists">Arrays, Lists, Vectors</a></li>
<li><a href="#tables">2D-Arrays, Datasets</a></li>
<li><a href="#trees">Trees</a></li>
<li><a href="#deflists">Hashtables, Dictionaries</a></li>
</ul>
<h2 id="lists">Arrays, Lists, Vectors<a href="#lists">#</a></h2>
<p>All programming languages have some way of storing a list of elements. While they are called different names in different languages and support different ways of adding elements they are very similar. HTML supports two kinds of single element lists, the <em>ordered and the unordered list</em>. When selecting which one of them you should use you just have to ask yourself: "Does this list make sense in another order?”. If it does it's an unordered list, if not it's an ordered one.</p>
<div class="highlight" data-language="HTML"><pre><span></span>Unordered list:
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Blue item<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Gray item<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Pink item<span class="p"></</span><span class="nt">li</span><span class="p">></span>
...
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
Ordered list:
<span class="p"><</span><span class="nt">ol</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Item 1<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Item 2<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Item 3<span class="p"></</span><span class="nt">li</span><span class="p">></span>
...
<span class="p"></</span><span class="nt">ol</span><span class="p">></span>
</pre></div>
<h2 id="tables">2D-Arrays, Datasets<a href="#tables">#</a></h2>
<p>Most languages also support some way of arranging your data in a two dimensional grid. The ordinary way is just letting people nest lists inside each other and get several dimensions like that. HTML has recognized the need for a simple way of marking up two-dimensional data in an easy way and therefore added the <em>table element</em>. Since two dimensions make the data a bit more complex to understand the HTML authors decided to add a few elements that describe what columns and rows mean. Below is a table with the essential elements for metadata added.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">table</span> <span class="na">summary</span><span class="o">=</span><span class="s">"Prices for apples in Sweden"</span><span class="p">></span>
<span class="p"><</span><span class="nt">caption</span><span class="p">></span>Table 1: Prices for various apples in Swedish stores<span class="p"></</span><span class="nt">caption</span><span class="p">></span>
<span class="p"><</span><span class="nt">thead</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Kind of apple<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Color<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Price<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">thead</span><span class="p">></span>
<span class="p"><</span><span class="nt">tbody</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Granny Smith<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Light Green<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>3 SEK<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Golden Delicious<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Yellow<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>6 SEK<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>McIntosh<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Golden<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>30 SEK<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">tbody</span><span class="p">></span>
<span class="p"></</span><span class="nt">table</span><span class="p">></span>
</pre></div>
<h2 id="trees">Trees<a href="#trees">#</a></h2>
<p>Sometimes you want to have a tree of data; it might be to display a nice view of your historical ancestors or simply the probabilities of something happening. Many programming languages have decided not to include a certain type for this and instead let programmers build their own type with the help of nodes and pointers. HTML instead relies on nested lists for this purpose. The example below shows a nested navigation menu in two levels:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Home<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>About this site<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Sections
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Blue Fishes
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Light blue Fishes<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Dark blue Fishes<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Black Fishes<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Red Fishes<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>Contact us<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
</pre></div>
<p>Worth a note is that lists only can contain list items, not other lists. This means that all sublist needs to be wrapped inside a list item like I have done above (the fishes are inside of Sections list item).</p>
<h2 id="deflists">Hashtables, Dictionaries<a href="#deflists">#</a></h2>
<p>Moving on we find the more advanced types of data. Quite often in programming we want to map a string to another string. This can be the case if we are building a dictionary or even if we want to store the price of different products. To me both of the above examples are cases where I would use a HTML <em>definition list</em>. Definition lists also has a way to mark that certain items might map to several other. By setting two dts after each other you make them both apply to the following dd.</p>
<p>I've made an example below of how to markup a list of properties.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">dl</span><span class="p">></span>
<span class="p"><</span><span class="nt">dt</span><span class="p">></span>Weight:<span class="p"></</span><span class="nt">dt</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>45 kg<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"><</span><span class="nt">dt</span><span class="p">></span>Length:<span class="p"></</span><span class="nt">dt</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>12 m<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"><</span><span class="nt">dt</span><span class="p">></span>Colors:<span class="p"></</span><span class="nt">dt</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>Blue<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>Red<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>White<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"><</span><span class="nt">dt</span><span class="p">></span>Cost:<span class="p"></</span><span class="nt">dt</span><span class="p">></span>
<span class="p"><</span><span class="nt">dd</span><span class="p">></span>500 SEK<span class="p"></</span><span class="nt">dd</span><span class="p">></span>
<span class="p"></</span><span class="nt">dl</span><span class="p">></span>
</pre></div>
<p>Definition lists where originally made to just store definitions (as the name suggests) but it's my opinion that they can be used for more than that. HTML lacks a lot of semantics and this is a way to extend it a bit. Feel free to leave a comment if you disagree.</p>
<p> </p>
<p>It's my opinion that HTML is good at marking up structure. Sure there are some types of data that can't be represented with HTML but the most common types are easy to do. Do you have more types to add to the list? Leave a comment!</p>
Web Development Pack2006-04-24T17:20:05+02:002006-04-24T17:20:05+02:00http://friendlybit.com/css/web-development-pack/Emil StenströmWhen I move to a new computer, I keep installing the same tools again and again. I always have problems finding them because they are spread out all over...
<p class="first">
When I move to a new computer, I keep installing the same tools again and again. I always have problems finding them because they are spread out all over the net. This article is an attempt to gather the links to the important web development tools in one place, as a resource for beginners.
</p>
<p class="first">
(<strong>Update </strong>2009-02-16<strong>: </strong>This is an update to an old article, I can't have old stuff polluting the site)
</p>
<h2 id="browsers-you-need">Browsers you need<a href="#browsers-you-need">#</a></h2>
<p>For modern web development today it's important to test in more than one browser. The current best practice is to first test in one that has good support for standards and then move on to the older ones and fix your site for them.</p>
<ul>
<li><strong><a href="http://www.mozilla.com/firefox/">Mozilla Firefox</a></strong> is a great browser and a serious challenger to Internet Explorer. The best web development feature of Firefox is all its extensions that are available. I have made a special section about good extensions to use below.</li>
<li><strong><a href="http://www.my-debugbar.com/wiki/IETester/HomePage">IE Tester</a></strong> helps to test your site in Internet Explorer. It is the browser that is used by most people over the world (because it ships with Windows, not because it’s the best one). The good thing with IE Tester is that it lets you run multiple versions of IE at the same time. No need for virtual machines. Consider hard if you <a href="/browsers/motivation-for-building-for-ie6/">need support for IE6</a>.</li>
<li><strong><a href="http://www.apple.com/support/downloads/safari.html">Safari</a></strong> / <strong><a href="http://www.google.com/chrome">Chrome</a></strong> are two good browsers based on the webkit rendering engine. Webkit's greatest merit is that it was one of the first browsers to complete the <a href="http://webstandards.org/action/acid2/guide/">Acid2 test</a>. Safari is also very popular on the Mac, so you probably you make sure it works.</li>
<li><strong><a href="http://www.opera.com/download/">Opera</a></strong> is another good browser with a little fewer users. The Opera team has put great effort to make any standards compliant site work in Opera so there’s no reason why your site shouldn’t work. There’s a few quirks though and it can therefore be worthwhile to test in it.</li>
</ul>
<h2 id="firefox-extensions">Firefox extensions<a href="#firefox-extensions">#</a></h2>
<p>Firefox extension system has made it possible for thousands of developers to make little snippets of code that add useful features to Firefox. There are a lot of extensions out there and so I’m sure I’m missing many but here’s the list that I just can’t live without (related to web development):</p>
<ul>
<li><strong><a href="http://getfirebug.com/">Firebug</a></strong> is the best thing that has happened to front-end development. It lets you click elements in the browser, and shows what HTML and CSS is needed to render the element you clicked. Excellent! Makes everything so much easier. Allows manipulation that is updated in realtime</li>
<li><strong><a href="http://chrispederick.com/work/webdeveloper/">Web development toolbar</a></strong> is an extension for Firefox that enables all kinds of useful features. It can give you borders around all your elements, it allows you to edit CSS in a sidebar and see the changes instantly, it allows you to remove images just to name a few. I can’t work at all without this one.</li>
<li><strong><a href="http://users.skynet.be/mgueury/mozilla/">HTML Validatior</a></strong> is the third must-have extension. It validates pages you visit on the fly, and shows a small red cross in the statusbar if you don't validate. Great way to quickly discover errors in your HTML.</li>
<li><strong><a href="http://www.colorzilla.com/firefox/">ColorZilla</a></strong> is extremely useful for finding out HTML color codes from images, something you will do a lot when coding graphic intensive pages.</li>
</ul>
<h2 id="other-programs-you-might-need">Other programs you might need<a href="#other-programs-you-might-need">#</a></h2>
<p>You're not only going to be surfing to your site, you're also going to need a program to write your code in, a graphics editor, and a FTP program to send your files off to the server with.</p>
<ul>
<li>I've always had problems finding a text editor that I liked. They either don't allow me to use the windows shortcuts I've learned to love, don't allow proper color coding of the languages I care about, don't handle setting up project in an easy enough manner, or handle character encoding badly. So I've just resorted to using whatever editor that fits best with the environment I'm currently working in. <strong><a href="http://www.netbeans.org/downloads/">Netbeans</a></strong> for Java, <strong>Visual Studio</strong> (non-free) for .NET, and <strong><a href="http://www.activestate.com/komodo_edit/">Komodo Edit</a></strong> for Python and PHP.</li>
<li><strong><a href="http://www.macromedia.com/software/fireworks/">Fireworks</a></strong> (non-free) is a graphics editor that lets me work with both vector and bitmap files. It allows filters that can be easily removed and tweaked without breaking the original. It also has a nice slice feature that let's me export parts of design mock-ups quickly. There's no free program worth its name.</li>
<li><strong><a href="http://filezilla-project.org/">FileZilla</a></strong> is a good open-source FTP program I keep coming back to. I fire it up and it just works every time. It's fairly feature-rich but you don't need to know all of it to get it going. If you do want to play with advanced stuff it's there. Easy to use, fast, many features.</li>
</ul>
<p>That's it. All that is left is for you to either agree or disagree.</p>
What’s happening?2006-04-20T23:28:09+02:002006-04-20T23:28:09+02:00http://friendlybit.com/other/whats-happening/Emil StenströmSorry for not posting for a while. There is a good reason though. In two days I'm arranging the biggest party ever with 9 of my friends. 280 people have...
<p>Sorry for not posting for a while. There is a good reason though. In two days I'm arranging the biggest party ever with 9 of my friends. 280 people have accepted the invitation and as you might understand there are countless things to fix. We are celebrating that we all soon have completed our university studies in computer science (5 years) so we do have a reason to be happy ;)</p>
<p>I will take up writing articles in a couple of days, I have many good ideas I think you will find interesting. Thanks for subscribing!</p>
What beginners ask for (and what I tell them)2006-03-27T22:22:07+02:002006-03-27T22:22:07+02:00http://friendlybit.com/css/what-beginners-ask-for-and-what-i-tell-them/Emil StenströmBeing in an IRC help channel lets you meet a lot of people. Many are fresh beginners that just wrote their first lines of CSS and stumbled over something...
<p>Being in an IRC help channel lets you meet a lot of people. Many are fresh beginners that just wrote their first lines of CSS and stumbled over something they found strange. When you look at their questions from a perspective you quickly find that many of them are repeated and come back over and over again. This article is an attempt to list a few of the important concepts that people seem to have trouble with.</p>
<h2 id="separation">Separation of content and design<a href="#separation">#</a></h2>
<p>Separation is the fundamental idea that CSS builds upon. Ten years ago there was only one way to make pages that worked across browsers: you mixed everything in one large file and copied that file if you wanted pages that looked similar. Then <a href="/css/interview-why-did-css-succeed/" title="Interview with Håkon Wium Lie">Håkon</a> and Bert came up with CSS and things got much easier. Their idea is to make the code easier to maintain by extracting everything that has to do with design, put it in an external file and link to that file when we want a certain look. CSS is all about design and HTML is all about content and structure.</p>
<p>Even though this sounds good in theory there are a lot of cases where it's hard to determine whether something is design or not. Is the company logo design or content? When you start thinking about those kinds of problems you know you're on the right track. You can find a couple of examples of the separation I'm talking about in my <a href="/css/beginners-guide-to-css-and-standards/">beginners guide</a>.</p>
<h2 id="clearing">Clearing floats<a href="#clearing">#</a></h2>
<p>Floats and clearing is another problem almost everyone has in the beginning. What I like to use when I explain how floats work is the old align-attribute on images. Long time ago, when you only could use HTML for design, and wanted the text to "flow around the image" you used:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/image.jpg"</span> <span class="na">align</span><span class="o">=</span><span class="s">"right"</span><span class="p">></span>
</pre></div>
</div><p>The above code is clearly design (placement of the image) so we should use CSS instead of HTML for this.</p>
<div class="correct"><div class="highlight" data-language="CSS"><pre><span></span><span class="nt">img</span><span class="p">#</span><span class="nn">id_of_image</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">right</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
</div><p>CSS is not restricted to float only images, all elements can be floated. This opens up to both new layout methods and confusion. To place three divisions side by side, just give them a width and float them. You can see a layout based on this in my <a href="/css/simple-css-templates/">article about layouts</a> or the <a href="/files/templates/?style=3columns_float_float_float&cols=3" data-no-instant>3-column example</a>.</p>
<p><em>Clear</em> is also important to know of. Setting <code>clear: both;</code> on an element makes it move downwards until it's below all previous floats. That was how the footer in the above example was made.</p>
<p>Floats and clears are not always easy to understand though. One thing people often ask about is what's wrong when their container isn't expanded to contain everything inside it. Eric Meyer excellently explains both that problem and its solution in the article <a href="http://www.complexspiral.com/publications/containing-floats/">Containing Floats</a>.</p>
<h2 id="validation">Validation is a timesaver<a href="#validation">#</a></h2>
<p>Why is validation so important? Because I just can't stand you forgetting your alt attributes? Because I think that valid pages are better than non-valid? No and No. It's because validation finds the simple errors. If I misspell width or some other property a validation will find it. If I nest my tags incorrectly a validation will find it. If I forget to close a quote in a link? A validation will find it. Validation is a great timesaver because it actually finds all the small errors that humans have trouble finding. To make validation even easier I use the <a href="http://users.skynet.be/mgueury/mozilla/">Html Validator extension</a> for Firefox. A little icon in the bottom right corner tells me when I have an HTML error. Validation is a great tool, use it.</p>
<h2 id="accessibility">Accessibility is not about blind users<a href="#accessibility">#</a></h2>
<p>It could be that I'm trying to explain why someone should add labels to their form. I say something in the lines of:</p>
<blockquote>
<p><strong>Me</strong>: "Not having labels hurts your site’s accessibility"</p>
</blockquote>
<blockquote>
<p><strong>User</strong>: "But I don't have any blind users on my site!"</p>
</blockquote>
<p>Accessibility is about making it easy for as many as possible to access your content. With, often simple, means you can make it much easier for people to access your site. Let me give you some examples or people your can help by thinking about accessibiliy.</p>
<table>
<thead>
<tr>
<th>User</th>
<th>How you can help</th>
</tr>
</thead>
<tbody>
<tr>
<td>Partly color blind</td>
<td>Don't use only color to convey information</td>
</tr>
<tr>
<td>People unable to use a mouse. Either because of some physical disability or simply that they are linux hackers and dislike it.</td>
<td>Make sure keyboard navigation works as intended</td>
</tr>
<tr>
<td>Young users or users with another native language than yours</td>
<td>Don't overcomplicate your text</td>
</tr>
<tr>
<td>People with a slow connection</td>
<td>Mind the size of your site</td>
</tr>
</tbody>
</table>
<p>The list could continue for a whole article. People from those groups would very much like to see your site and buy your stuff just like anyone else. Read up on the basics of accessiblity, it helps a lot of people. Robert Johansson has written a nice article about how you could <a href="http://www.456bereastreet.com/archive/200603/evaluating_website_accessibility_part_1_background_and_preparation/">evaluate your website's accessibility</a>.</p>
<h2 id="harder">Some things are harder to do with CSS, that does not mean CSS is a bad language<a href="#harder">#</a></h2>
<p>People that are switching from tables to CSS often complain about what a bad language CSS is for not supporting <em>[insert favourite feature]</em>. I did so too in the beginning. What makes me like the language is all the other powers it gives me. It is not possible to do everything as easily with CSS as it is with tables. But other things are much easier, and some things aren't even possible with tables. There are good parts and bad parts and to me the good parts greatly outweigh the bad ones.</p>
<h2 id="equal">Equal height columns<a href="#equal">#</a></h2>
<p>The last thing I'm going to talk about in this article is equal height columns. The problem is that your have two or three columns of content that stretch down the page. You want the columns to stretch as far as the longest column but the content inside does not expand the columns that far.</p>
<p>This problem is most easily solved by a technique known as <em>faux columns</em>. Add a container to the columns you have and then add a background image to that container. The image will repeat down that page and make it look like your columns take up exactly as much vertical space. I've added a <a href="/files/templates/?style=faux_columns&cols=3&nofooter=1" data-no-instant>faux column example</a> for you to look at.</p>
Challenge: What’s the worst you can do?2006-03-11T16:09:26+01:002006-03-11T16:09:26+01:00http://friendlybit.com/css/challange-whats-the-worst-you-can-do/Emil StenströmAfter reading through the comments on my levels of CSS article I find that I few people seem to think that the article is a way to ridicule beginners. It's...
<p>After reading through the comments on my <a href="/css/levels-of-css-knowledge/">levels of CSS</a> article I find that I few people seem to think that the article is a way to ridicule beginners. It's not. It's a way to document the steps that I think I have climbed. Some people also thought that this set of levels is a good indicator of how good sites you will make. That's also false. Being Level 5 or 6 in the list means that you are a good <em>coder</em>, nothing else. It does not mean that a site you make is any good, I've seen many sites that have great code but that still makes me want to kill someone. Don't confuse good web developers with good coders. "Don't be a <a href="http://www.molly.com/2006/02/23/how-to-sniff-out-a-rotten-standardista/">rotten standardista</a>" as Molly Holzschlag would put it.</p>
<h2 id="the-challenge">The challenge<a href="#the-challenge">#</a></h2>
<p>To give you a perspective of how bad it really could be I'm challenging all the readers of Friendly Bit. It's kind of a competition (with no prize) about who can make the worst site. The rules are simple; you are to construct a page, using HTML and CSS (and Javascript if you think you need it) that has a design that is as hideous as possible. I want pages that make my eyes bleed, that make small children cry and makes <a href="http://maddox.xmission.com/">Maddox</a> write hate articles about you. Think of all the good things you've learnt and do the opposite.</p>
<h2 id="inspiration-for-a-truly-hideous-design">Inspiration for a truly hideous design<a href="#inspiration-for-a-truly-hideous-design">#</a></h2>
<p>I won't be giving out any prize but what I can do is help you with some ideas of bad code.</p>
<p>Make use of the <code><marquee></code> tag. It makes any content inside it scroll in the speed and direction you choose. Did you know that you can wrap <code><body></code> in a marquee tag? That's right, your entire page will move automatically. You can also nest several marquee tags inside each other. Ohh yeah!</p>
<p>Another good tag you can use is the <code><blink></code> tag. Can it be applied to, say, a table? I hear you ask. But of course. You can have a full screen blinking table on your company homepage.</p>
<p>Continuing with the good ideas we have the oldschool <em>frames</em> we all have come to like. Did you know that there are no set upper limit on the number of frames you can load? You can have thousands of them! You can even mark up a whole tabular grid with frames alone.</p>
<p>This challange is about <em>terrible code</em> as much as it's about terrible design. So don't go with well-formed or the basic foundations of HTML. Did you even try putting tags inside other tags? <code><font <font size="2"> size="3"></code> is quite fantastic don't you think? Make your page upside down by adding the <code><head></code> below the <code><body></code>, but only after you have added your own <code><neck></code> tag to the mix. Surprise me!</p>
<h2 id="how-to-accept-the-challenge">How to accept the challenge<a href="#how-to-accept-the-challenge">#</a></h2>
<p>To join all of this you just have to make the page, put it up on your server and link to it here. Post a link as a comment or simply trackback (link to this post) from your own blog and it will show up here.</p>
<p>Finally: Don't forget the lesson behind all this. When you see a site with bad code, know that there's a lot of much worse sites out there.</p>
Interview: Why did CSS succeed?2006-03-02T12:14:22+01:002006-03-02T12:14:22+01:00http://friendlybit.com/css/interview-why-did-css-succeed/Emil StenströmWhen you are looking to reach the upper skill levels of a technique it's always a good idea to start with looking back. The history often says much about...
<p>When you are looking to reach the upper skill levels of a technique it's always a good idea to start with looking back. The history often says much about the fundamental building blocks and why they work like they do. What were the basic driving forces behind it? What need did it fill? When examining those kinds of questions you can get a far deeper knowledge of what you are working with.</p>
<p>In an attempt to gain some of that knowledge I contacted the authors of <a href="http://www.w3.org/TR/REC-CSS1-961217">Cascading Style Sheets, level 1</a> (CSS1, notice the nice background image) and asked a few questions about the development on the first CSS specification.</p>
<p><a href="http://people.opera.com/howcome/">Håkon Wium Lie</a> promptly answered my questions. He's currently the CTO of Opera, making one of the better browsers out there. This was done by email so don't be surprised if earlier answers reference later ones :) Here's the interview:</p>
<p><strong>Emil Stenström:</strong></p>
<p>First I'd like to extend a big thank you from the web development community for coming up with the fantastic idea that is CSS. The language has become a huge success and thousands of people daily exchange ideas of how to best use its power CSS. New people also learn the language each day and big corporations rebuild their sites because of it.</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Thank you for your kind words. As we'll get back to later in the interview, CSS is the result of many people's ideas and efforts. Without a strong community around CSS, the specification would not have succeeded.</p>
<p><strong>Emil Stenström:</strong></p>
<p>1994 when CSS where first proposed there were many different languages available that also made it possible to style web pages. What arguments where there that made people choose CSS instead of any of the others?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>There were, indeed, a bunch of proposals on the table. First, there were the style sheet languages that had been developed before the web. FOSI, DSSSL, and "P" should be mentioned. Second, there were around ten different style sheet proposals for the web. Several of them were based on earlier languages, but most of them brought new ideas to the table. There was also a healthy interchange of ideas and CSS picked up its shares.</p>
<p>In the end, I think CSS succeeded because it took the web — as opposed to a paper-centric publishing model — seriously. The web introduced some new requirements for style sheet languages, including progressive rendering, screen-based formatting (e.g., pixel units), media-specific style sheets, link styling, and a certain robustness in case one resource (e.g., the style sheet itself) is missing.</p>
<p>It so happens that I'm about to defend my PhD thesis on this subject. So, if you're interested in the history of style sheet languages in the context of the web, I can offer you a few hundred pages to read.</p>
<ul>
<li><a href="http://people.opera.com/howcome/2006/phd">http://people.opera.com/howcome/2006/phd</a></li>
</ul>
<p><strong>Emil Stenström:</strong></p>
<p>I can imagine that getting the language from the idea stage to it being accepted by the W3C as a recommendation was anything but a walk in the park. There where surely other authors that wanted their language to succeed instead. How much did work did you put in to promoting the language? Did the features it contain work in promoting the language in itself?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Most of the ten proposals I mentioned above were not serious contenders. The one proposal that had the most backing, beside CSS, was DSSSL-Lite. Many people in the SGML camp were upset when W3C (on March 5, 1996) announced that <q>The style sheet efforts will be based on Håkon Lie's Cascading Style Sheets (CSS) initiative, to be further refined by a group of experts within the W3C.</q></p>
<ul>
<li><a href="http://www.w3.org/Style/960305_News.html">http://www.w3.org/Style/960305_News.html</a></li>
</ul>
<p>One important reason for W3C promoting CSS was support from implementors. Microsoft, amongst others, had committed to implementing CSS at a Style Sheet workshop held in 1995. Compared to DSSSL-Lite, CSS was easier to support since it wasn't Turing-complete and didn't require a transformation step. So, in a way, it was the simplicity — the <strong>lack</strong> of features — that won people over.</p>
<p>The fact that Microsoft haven’t followed up on their promises of supporting CSS and other web standards is very sad. I proposed the Acid2 test to support them along the way:</p>
<ul>
<li><a href="http://news.com.com/The+Acid2+challenge+to+Microsoft/2010-1032_3-5618723.html?tag=nefd.ac">The Acid2 challenge to Microsoft</a></li>
<li><a href="http://www.webstandards.org/acid2">http://www.webstandards.org/acid2</a></li>
</ul>
<p><strong>Emil Stenström:</strong></p>
<p>CSS got accepted as a recommendation and browsers started to implement the language. This was the real test to see if the specifications where clear enough. Are there sections or parts of the first specification that you wish that you had written differently or emphasized more?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>All in all, I'm very happy with how CSS1 has stood the test of time. Compared to many other standards, there are few ugly compromises and not much feature creep. Looking back, I probably would have argued to drop a few features that havn't seen much use (first-letter and first-line), and I would have split a few overloaded properties ('display' and 'white-space' come to mind).</p>
<blockquote>
</blockquote>
<p>I CSS2, I think we should have seen the rise of JavaScript as an opportunity rather than a threat. A 'style sheet object model' should have been built into the thing rather than being an afterthought.</p>
<p><strong>Emil Stenström:</strong></p>
<p>Many people shift between thinking about CSS as something written by a few people, perhaps even only the two of you, and it being written by an organization of thousands of people. Which of those are closest to the truth? How many are approximately involved in the writing of a specification (ie. CSS 2)?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Lots of people have to be involved. Otherwise, a specification is likely to die a lonely death. In the beginning, however, it's better to be only a few people in order to establish a foundation quickly. For CSS, that happened in the summer of 1995 when Bert Bos and I worked intensely around a white board for a few weeks. He came up with many key ideas, including the forward-compatible parsing.</p>
<p>After that, CSS became a work item of the W3C's HTML working group before getting a working group of its own in 1997. CSS2 came out of that working group. I would estimate that around 10-15 people were actively involved in working out the design of CSS2, while four people are listed as "editors". CSS1 didn't have "editors", it had "authors".</p>
<p>Also, there was a strong community of users on the www-style mailing list that helped us shape the specification, write test suites, and complain in all the right places and do all the other things that are necessary to make a web standard succeed. The real work starts when the specification is finished…</p>
<p><strong>Emil Stenström:</strong></p>
<p>Attribute selectors and generated text where available in one of the early browsers, Argo, over 10 years ago. Those features were not included in the first spec but instead moved to CSS 2. Why were they moved and do you have any ideas of why they are still not implemented by some browsers? Do you have any ideas of things we could do to get implementations available faster in the different browsers?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Generated content is very cool and it's sad to see that Microsoft's IE7 — coming out 8 years after CSS2 became a Recommendation — will not support it. This is remarkable since Dean Edwards has added support for generated content in his "IE7" project; by adding a link to a JavaScript on our page, IE will happily display CSS2 generated content. So, I believe the decision not to fully support CSS in IE is political rather than technical. Thankfully, there are some other browsers around. May I mention Opera, here?</p>
<ul>
<li><a href="http://www.opera.com/">http://www.opera.com/</a></li>
</ul>
<p><strong>Emil Stenström:</strong></p>
<p>Talking more about the future of CSS, there is much work going on with the CSS 3 spec. We will see text shadows, gradients, and multi column layouts, just to name a few. Which new features are to most exciting to you? Is there anything that isn't in the spec yet but will soon be that you want to tell us about?</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Personally, I'm very exited about the print-related features. Being able to write our book in HTML and style it with CSS was great fun and confirmed our belief in CSS beyond screen use. It required a few features not present in CSS2 and they will be described in CSS3.</p>
<ul>
<li><a href="http://www.alistapart.com/articles/boom">http://www.alistapart.com/articles/boom</a></li>
</ul>
<p>Just like I got involved with Opera to ensure that someone implemented CSS correctly, I’m now also involved with Prince to ensure that someone gets CSS printing right.</p>
<ul>
<li><a href="http://www.princexml.com">http://www.princexml.com</a></li>
</ul>
<p><strong>Emil Stenström:</strong></p>
<p>Thanks again for taking the time to answer these questions. Perhaps some of my readers will be the ones coming up with the next big thing™.</p>
<p><strong>Håkon Wium Lie:</strong></p>
<p>Cheers</p>
Min-width for IE revisited2006-02-22T21:41:56+01:002006-02-22T21:41:56+01:00http://friendlybit.com/css/min-width-for-ie-revisited/Emil StenströmMuch has been written over the years of how to get min-width to work in Internet Explorer (IE). Min-width works almost like width but it only sets a lower...
<p>Much has been written over the years of how to get min-width to work in Internet Explorer (IE). Min-width works almost like width but it only sets a lower bound on the width ("You can't get any narrower than this!"). Very useful when building layouts that are supposed to work on many screen resolutions. This article is a remake of Stu Nicholls variant but removing most of the divs he uses. <a href="/files/minwidth_for_IE/" data-no-instant>An example is availiable</a>.</p>
<h2 id="if-all-browsers-supported-standards">If all browsers supported standards<a href="#if-all-browsers-supported-standards">#</a></h2>
<p>The question that triggered this article was someone that wanted the page to be 90% wide but no less than 500px. For those of you that know CSS2 you know that this can be done by simply setting:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">element</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">90</span><span class="kt">%</span><span class="p">;</span>
<span class="w"> </span><span class="k">min-width</span><span class="p">:</span><span class="w"> </span><span class="mi">500</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Since no versions of IE support the min-width property we will have to try something else.</p>
<h2 id="what-has-been-done-before">What has been done before?<a href="#what-has-been-done-before">#</a></h2>
<p>To solve this problem there has been suggestions of all sorts of things: <a href="http://www.doxdesk.com/software/js/minmax.html">Javascript</a>, Proprietary CSS expressions, One that doesn't handle both width and min-width, and <a href="http://www.webreference.com/programming/min-width/">One using four (!) extra divs</a>. When looking at the different solutions I quickly came to the conclusion that I didn't want to use javascript. It would be better if it could be accomplished using CSS only. That rules out the two first versions. Dave Shea's does not handle both width and min-width. The last one uses a lot of divs, are really all of them needed?</p>
<p>Stu's solution is set to work in IE 5, an old outdated browser and by removing the code to make it work for that one we will be able to lose some of the code.</p>
<p>IE5 has a broken <a href="http://www.brainjar.com/css/positioning/">box model</a>, so you can't set both margin/border/padding and a width on the same container and get consistent behaviour across browsers. I know of two ways to sidestep that bug: The first one is using the ugly <a href="http://www.tantek.com/CSS/Examples/boxmodelhack.html">box model hack</a> which incorporates a parsing bug in how IE 5 handles the voice-family property. The other way is to use two containers and set the width on one of them and the margin/border/padding on the other. Stu uses the latter variant and therefore has two unnecessary divs. Two down, and counting!</p>
<p>Next up we can use the <code><body></code> tag just like if it was a div, setting the width and min-width on that one. Another div bites the dust. If we can handle using a solid background color another one can be left out.</p>
<p>With everything summed up we can get <a href="/files/minwidth_for_IE/" data-no-instant>min-width for IE on any container using only one extra div</a>. This works under the constraint that we don't support IE 5 and that we can handle a single color background. I hope that helps someone out there.</p>
Extra fluid layouts with javascript2006-02-13T01:00:31+01:002006-02-13T01:00:31+01:00http://friendlybit.com/css/extra-fluid-layouts-with-javascript/Emil StenströmI'm a big fan of vector graphics. Because of that I love Macromedia Fireworks and the way it handles all elements like vectors. The good thing about that is...
<p>I'm a big fan of vector graphics. Because of that I love Macromedia Fireworks and the way it handles all elements like vectors. The good thing about that is that they can be resized and zoomed without them losing their sharpness.</p>
<p>This got me thinking about how to add some vectorization to CSS layouts. My idea was that you should let the width of the screen decide the font-size of, for example, your headers. This could make for nice fluid layouts and might even add to usability in some cases. There are probably other uses for this but I leave that to you, please use the comments if you come up with something.</p>
<p>Start by having a look at the <a href="/files/window_fontsize/" data-no-instant>dynamic font-size example</a> just so we're talking about the same thing. Try resizing the window and reloading and see that the headers really do adapt to the width of the browser window.</p>
<h2 id="how-its-done">How it's done<a href="#how-its-done">#</a></h2>
<p>First we need a way to meassure the width of the text in the default font. For this I use my own little getTextWidth() that were constructed in my <a href="/css/line-breaking-with-javascript/">line-break script</a>. It simply takes a piece of text, attaches it to the page, meassures it's width and removes it again.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">ea</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s2">"span"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">ea</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">;</span>
<span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">ea</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ea</span><span class="p">.</span><span class="nx">offsetWidth</span><span class="p">;</span>
<span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">ea</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">len</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Ok, now we know the width of some text in it's non formated state. Next up is to scale it as much as needed.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">scaleUp</span><span class="p">(</span><span class="nx">elem</span><span class="p">,</span><span class="w"> </span><span class="nx">targetWidth</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">blockWidth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">elem</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">defaultSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">elem</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">fontSize</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">'100%'</span><span class="p">)</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">newSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="mf">0.9</span><span class="o">*</span><span class="nx">targetWidth</span><span class="o">/</span><span class="p">(</span><span class="nx">blockWidth</span><span class="o">/</span><span class="nx">defaultSize</span><span class="p">))</span>
<span class="w"> </span><span class="nx">elem</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">fontSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">newSize</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">"%"</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>As you see scaleUp() determines a percentage by looking at three things: it's unformated width, it's current width and the target width. Font-size and text width does not seem to follow eachother perfectly so an additional multiplication by 0.9 is needed.</p>
<p>This handy little function is then called with the element you want to scale and the width in pixels of how wide you want it. The calls look something like this:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">element</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"h1"</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">offsetWidth</span><span class="p">;</span>
<span class="nx">scaleUp</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span><span class="w"> </span><span class="nx">width</span><span class="p">);</span>
</pre></div>
<p>That's it, hope you find some fun use for it.</p>
<p><strong>Update:</strong> After doing some research I see that Eric Meyer is already using something like this in his <a href="http://www.meyerweb.com/eric/tools/s5/">slideshow system S5</a>. Well well, it was a funny exercise none the less.</p>
Frames or Iframes with CSS2006-02-01T23:50:59+01:002006-02-01T23:50:59+01:00http://friendlybit.com/css/frames-or-iframes-with-css/Emil StenströmA frequent request from people new to CSS is trying to get a behaviour similar to frames while only using CSS. Many have read that frames have a lot of...
<p>A frequent request from people new to CSS is trying to get a behaviour similar to frames while only using CSS. Many have read that frames have a lot of problems but do not know much more than that. This article will try to explain why frames are bad and what to do about it.</p>
<ul>
<li><a href="#why">Why are traditional frames such a bad thing?</a></li>
<li><a href="#scrollbar">Getting a scrollbar on any element using CSS</a></li>
<li><a href="#traditional">Mimicking traditional frames</a></li>
</ul>
<blockquote>
<p><strong>Update</strong>: I've updated this technique <a href="/css/position-fixed-css-templates/">using position: fixed in a new article</a>, have a look at those templates instead! (Although this article is still good for background information).</p>
</blockquote>
<h2 id="why">Why are traditional frames such a bad thing?<a href="#why">#</a></h2>
<p>Let me start by just listing a few bad things about frames.</p>
<ul>
<li><strong>Prevents users from bookmarking</strong> the exact page they're on. Instead the bookmark will lead to the frameset. This is clearly not a good choice for larger sites where finding a certain page might be a problem, but even users on smaller sites might find it annoying. I do.</li>
<li><strong>Poor support by some parsers</strong> leads to problems. Many screen readers, mobile phones, and search engines have problems parsing frames. This means some of your users might miss out on your content.</li>
<li><strong>Content order</strong> problems. Just like with tables, frames give screen readers problems when deciding which order to read the frames. If it reads a 2×2 frameset will not know whether to read the content like two rows or like two columns. The order might be important for understanding the content and frames has nothing built-in to help with that.</li>
<li><strong>Search engines</strong> might split the ranking up on the different pages. I just discovered this by looking at one of my old pages (no, I won't show it, it's terrible :). There, the <a href="http://www.webworkshop.net/pagerank.html">PageRank</a> has been split up on the framed pages and the frameset has no rank whatsoever.</li>
<li><strong>Invalid code</strong>. If you're using separate frames for navigation and content your links will need the <code>target</code> attribute to make links from the navigation frame open in the content frame. That attribute is not supported when using a strict doctype so you will have to use transitional. The doctype won't matter if you want to get rid of borders cross-browser though, to do that you need invalid markup.</li>
<li><strong>Printing is a problem</strong>. How should the different frames be handled while printing? There's no good solution to this.</li>
</ul>
<p>People that are good with javascript sometimes say they like frames because they make it possible to save information about the user even though the user clicks links. A variable can be saved in a frame and be accessible to the other frames even after they are reloaded. Another pro-frames reason frequently heard is that it saves overhead since not the entire page gets reloaded.</p>
<p>Personally I think that the first is a bad reason to use frames. Using server side scripting to save session info is much more robust since that will mean the applications still work if the user reloads the page. The other reason of only reloading a part of the page is nowadays done by using javascript together with XMLHttp (some like to call it AJAX). To me, the bad parts of frames greatly weigh over, even for applications.</p>
<h2 id="scrollbar">Getting a scrollbar on any element using CSS<a href="#scrollbar">#</a></h2>
<p>Aside from all of the above frames are not structure. Think about it. When working with frames you define that you want a couple of rows and columns, which should scroll and which shouldn't, and which should have borders. These are things that many of us would never dream of doing with tables but some still use frames like that.</p>
<p>Instead we should define that kind of design in our CSS files. How? By using a few lines of code you can easily limit any element to a certain width/height and let it scroll if the content overflows that size.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">p</span><span class="p">></span>Here's some sample content that I would like to scroll<span class="p"></</span><span class="nt">p</span><span class="p">></span>
</pre></div>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">p</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">80</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">overflow</span><span class="p">:</span><span class="w"> </span><span class="kc">auto</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>It's easy, you're saying: "limit the paragraph to this size and give the box a scrollbar if the content gets too big" (Other valid values for overflow are "hidden" and "scroll". The former just cuts everything that sticks out, that latter adds the scrollbars even if they're not needed).</p>
<p>The above method works when you want something that's similar to iframes but it doesn't work right away for traditional frames. Those usually span the whole width or height of the page and leave the rest of the page scrolling. But what stops us from taking any element and stretching and placing it like a frame? Nothing. Let's do it.</p>
<h2 id="traditional">Mimicking traditional frames<a href="#traditional">#</a></h2>
<ul>
<li><a href="/files/frames/columns.html" data-no-instant>Two columns with left fixed</a></li>
<li><a href="/files/frames/columns_navright.html" data-no-instant>Two columns with right fixed</a></li>
<li><a href="/files/frames/rows.html" data-no-instant>Two rows with a fixed top</a></li>
</ul>
<p>The idea here is to use divisions to group our content. Then position those divisions as if they where frames and limit their site and set <code>overflow: auto</code> like we did above. Frames use the syntax <code>cols="200,*"</code> to say that the first column should be 200px wide and the second one "cover what's left". The second part is a bit harder to do with CSS.</p>
<p>There's no way to say 100%-200px but there's a trick we can use: floats push the content away. So if we set a width on the left block to 200px and float it left, the other block will be as wide as possible (default for block level elements) but it's content will be pushed 200px to the right. Here's an example of <a href="/files/frames/columns.html" data-no-instant>two columns with a fixed left</a> in action. By just changing float: left; on navigation to float: right; we get the other example: <a href="/files/frames/columns_navright.html" data-no-instant>Two columns with the right one fixed</a>.</p>
<p>(Technical note: we don't need to add any margin-left since <a href="http://www.mezzoblue.com/archives/2005/03/03/clearance/">overflow: auto; clears</a> too).</p>
<p>The above works well for columns but what if we need rows instead? When using frames we specify <code>rows="100,*"</code> and as I said this is not possible directly with CSS. We can't use the above trick either since we're dealing with height here. Setting <code>height: 100%</code> will just make it as high as the window, leaving no space for the other row. The solution here is to cheat a bit. If we make the first column 100px high and the lower one 100% high but then remove the first one from the flow we will be pretty close. The first row will be on top of the other one but that can easily be solved by adding a padding-top the same height as the first row.</p>
<p>We're almost there now, one last thing: the latter row scrolls on top of the first one because of the order in the source (latter elements stack on top of earlier ones). So what we do is force the first one on top with position: relative. This solves the problem except that it also covers the scrollbar now. An easy (and ugly fix) is to add a margin-left of 16px to the top column making the scrollbar visible again. Browsers seem to use the same scrollbar width so that's it, an <a href="/files/frames/rows.html" data-no-instant>example of frame rows</a> using CSS.</p>
<p>I've tested this in IE 6, FF 1.5 and Opera 8.5 on WinXP and it seems to work fine. Broken in any other browsers? Let me know through the comments.</p>
<p>When looking at this I see that this is also a good way to mimick blocks that are <code>position: fixed</code>, something that doesn't work in IE. This method might be good in a situation where you need that one.</p>
Google statistics over HTML usage2006-01-25T20:56:18+01:002006-01-25T20:56:18+01:00http://friendlybit.com/html/google-statistics-over-html-usage/Emil StenströmGoogle Code has done extensive research over the use of HTML today. Since this is Google doing the job they had access to an enormous amount of data, over a...
<p>Google Code has done extensive research over the use of HTML today. Since this is Google doing the job they had access to an enormous amount of data, over a billion documents where analysed. What does the report conclude? Pretty much what we already know: people don't use HTML for structure like its intended.</p>
<p>Here are some examples of strange usage in the report:</p>
<ul>
<li><code><head></code> is used more often than <code><html></code>. No comment.</li>
<li><code><table></code> is the ninth most used element. I have serious doubts that this is due to the amount of tabular data on the web.</li>
<li>The third most used classname is "title" and the fourth "small". The first could probably be replaced by a header tag, the other one should certainly be set by CSS since it's style.</li>
<li>Half of all <code><body></code> elements contains the "bgcolor" attribute. If this isn't style, what is?</li>
</ul>
<p>The report tells a lot about the shape of the web. If I only could get more people to read my <a href="/css/beginners-guide-to-css-and-standards/">beginners guide</a>…</p>
Four things to get you tagged2006-01-25T23:00:32+01:002006-01-25T23:00:32+01:00http://friendlybit.com/other/four-things-to-get-you-tagged/Emil StenströmThere's a few questions circling the blogsphere. I better pass them on just to avoid the angry CSS gods. Four jobs I've had in my life# Folder of mighty...
<p>There's a few questions circling the blogsphere. I better pass them on just to avoid the angry CSS gods.</p>
<h2 id="four-jobs-ive-had-in-my-life">Four jobs I've had in my life<a href="#four-jobs-ive-had-in-my-life">#</a></h2>
<ul>
<li>Folder of mighty envelopes</li>
<li>Cutter of complex vegetables</li>
<li>Administrator of Nokia Online</li>
<li>Web developer for my own company</li>
</ul>
<h2 id="four-movies-i-can-watch-over-and-over">Four movies I can watch over and over<a href="#four-movies-i-can-watch-over-and-over">#</a></h2>
<ul>
<li>Magnolia</li>
<li>Matrix</li>
<li>Memento</li>
<li>Mind the Gap</li>
</ul>
<p>Oh, that's only the ones on M… :)</p>
<h2 id="four-places-i-have-lived">Four places I have lived<a href="#four-places-i-have-lived">#</a></h2>
<p>Four places? Let's make all four of them Stockholm, Sweden.</p>
<h2 id="four-tv-shows-i-love-to-watch">Four TV shows I love to watch<a href="#four-tv-shows-i-love-to-watch">#</a></h2>
<p>No, no, NO! I can smile and nod when people talk about Desperate Housewives or Lost, but truth is I don't have a clue. I'd rather read some feed than look at non-interactive TV ;)</p>
<h2 id="four-places-i-have-been-on-vacation">Four places I have been on vacation<a href="#four-places-i-have-been-on-vacation">#</a></h2>
<ul>
<li>Kobenhavn, Denmark</li>
<li>Amsterdam, Netherlands</li>
<li>Paris, France</li>
<li>Marseille, France (all four on the same trip)</li>
</ul>
<h2 id="four-of-my-favourite-dishes">Four of my favourite dishes<a href="#four-of-my-favourite-dishes">#</a></h2>
<ul>
<li>Pancakes!
I can't really think of four dishes that I like particularly much. I'm a student so noodles and spaghetti are the frequent ones.</li>
</ul>
<h2 id="four-websites-i-visit-daily">Four websites I visit daily<a href="#four-websites-i-visit-daily">#</a></h2>
<ul>
<li>Stylegala - Webdev community</li>
<li><a href="http://www.dooce.com">Dooce</a> - Great humourus writer (about life)</li>
<li><a href="http://www.waiterrant.net">Waiterrant</a> - Also a great writer (about being a waiter)</li>
<li><a href="http://www.d.kth.se" lang="sv">Datasektionen</a> - The program on the university where I study</li>
</ul>
<h2 id="four-places-i-would-rather-be-right-now">Four places I would rather be right now<a href="#four-places-i-would-rather-be-right-now">#</a></h2>
<ul>
<li>Out travelling with someone I like</li>
<li>Ireland - Seeing if the Pubs are as nice as they say</li>
<li>Iceland - Trekking, climbing, all kinds of adventure sports</li>
<li>Prague - Dancing in one of the great techno clubs I've heard of</li>
</ul>
<h2 id="four-bloggers-i-am-tagging-all-from-the-css-help">Four bloggers I am tagging (all from the #CSS help channel)<a href="#four-bloggers-i-am-tagging-all-from-the-css-help">#</a></h2>
<ul>
<li>G1nx</li>
<li><a href="http://personaldevelopment.ca/">trevor</a></li>
<li><a href="http://www.csarven.ca">csarven</a></li>
<li>taare</li>
</ul>
Building a poker template2006-01-23T03:31:06+01:002006-01-23T03:31:06+01:00http://friendlybit.com/css/semantic-poker-template/Emil StenströmThis is the first article in a series of niche templates I'm building. You can have a look at the finished template before we start if you want. About the...
<p>This is the first article in a series of <a href="/css/building-niche-sites-with-standards/">niche templates</a> I'm building. You can have a look at the <a href="/files/poker/?style=positioning&style2=decoration" data-no-instant>finished template</a> before we start if you want.</p>
<h2 id="about-the-niche">About the niche<a href="#about-the-niche">#</a></h2>
<p>Today's topic is <em>Poker sites</em>. Poker, and card games overall, are hot these days and they are all over news. There are TV commercials for big international gambling sites even here in Sweden. Being in that kind of spotlight and receiving massive traffic must make those sites better than the rest, don't you think? Let's <a href="http://www.google.com/search?q=poker">google for "poker"</a> and have a look at the top 10 results (23 Jan 2006).</p>
<table summary="A look at the web standards compliance of poker sites">
<tr>
<th title="Placement in Google">
#
</th>
<th>
Site name
</th>
<th>
Doctype
</th>
<th>
Validation errors
</th>
<th>
Layout method
</th>
</tr>
<tr>
<th>
1
</th>
<td>
Pokerroom.com
</td>
<td class="almost">
Transitional
</td>
<td class="incorrect">
22 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
<tr>
<th>
2
</th>
<td>
Poker.com
</td>
<td class="correct">
Strict
</td>
<td class="incorrect">
62 errors
</td>
<td class="correct">
CSS
</td>
</tr>
<tr>
<th>
3
</th>
<td>
Pokerstars.com
</td>
<td class="incorrect">
None
</td>
<td class="incorrect">
48 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
<tr>
<th>
4
</th>
<td>
Pokerpages.com
</td>
<td class="incorrect">
None
</td>
<td class="incorrect">
336 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
<tr>
<th>
5
</th>
<td>
Pagat.com Poker
</td>
<td class="incorrect">
None
</td>
<td class="incorrect">
52 errors*
</td>
<td class="correct">
None
</td>
</tr>
<tr>
<th>
6
</th>
<td>
Worldpokertour.com
</td>
<td class="almost">
Transitional
</td>
<td class="incorrect">
56 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
<tr>
<th>
7
</th>
<td>
Pacificpoker.com
</td>
<td class="incorrect">
None
</td>
<td class="incorrect">
72 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
<tr>
<th>
8
</th>
<td>
Partypoker.com
</td>
<td class="almost">
Transitional
</td>
<td class="incorrect">
22 errors*
</td>
<td class="correct">
CSS
</td>
</tr>
<tr>
<th>
9
</th>
<td>
Paradisepoker.com
</td>
<td class="almost">
Transitional
</td>
<td class="almost">
1 error
</td>
<td class="correct">
CSS
</td>
</tr>
<tr>
<th>
10
</th>
<td>
Homepoker.com
</td>
<td class="incorrect">
Broken
</td>
<td class="incorrect">
146 errors
</td>
<td class="incorrect">
Tables
</td>
</tr>
</table>
<p class="first">
*) These sites required that we set a character set manually to even see how many errors there were.
</p>
<p>What do we see up there? Poker.com and Paradisepoker.com do pretty well. Poker.com uses Strict doctype which means that their validation is stricter than the others, but 62 errors is still too much. Paradisepoker.com almost validates as Transitional which is a good thing compared to the other sites in the list.</p>
<p>Three sites use CSS for their layouts instead of tables. This is a good thing and they should be commended for it. However, that does not mean that they can't be <em>better</em>. All three with CSS layouts overuse divisions and spans terribly, often making the page a mess without CSS turned on.</p>
<p>Does this guy do nothing more than whine? I hear you ask. Yes I do. What I will do is nothing special; any one of you reading this could have done it yourself. I'm going to build a simple HTML document mimicking the front page of a poker site. If you are planning to build a site like that (or even if you are the developer of one of the sites above), you should definitely keep reading. The idea with all of this is to make it easier for people to follow the standards.</p>
<p>I will only include the front page of the site but it won't be hard to transform it to something simpler later on. Remember the purpose here: to show that it's possible to combine logical markup, valid code and make it look just the way you want it to. We need some kind of content though, so let's start with that.</p>
<h2 id="plan-what-features-you-want">Plan what features you want<a href="#plan-what-features-you-want">#</a></h2>
<p>The features for the template will be my picks of the top10 above. Let's put some time on analyzing what features a decent poker site has.</p>
<p>The purpose of most of the sites seems to be to <em>get people to play</em> on their site. Most have some kind of client that is easily available from the front page and that button is the most important part of the page. Aside from that we need features to build a community around the game. Let's pick <em>a forum</em> as our community builder. Beginners need to have somewhere to <em>learn the basics</em> and everyone might need <em>support</em> from experienced staff sometimes. To build a good community you might also need news of some kind, displaying the largest prizes might give the site more players. Finally, all respectable sites have some info <em>about the company</em> behind it and if the site is big, they have a <em>search</em>. We want to earn some money too so let's add in a little advertisement. Sum this up in a list with descriptions.</p>
<ul>
<li><strong>Play poker button</strong>: One big button telling people to click it.</li>
<li><strong>Beginners guide and support</strong>: Show on the front page that you don't need to be a pro to play and provide a quote from a professional player that illustrates this. Link directly into the guide to show experienced users that there might be something there for them too. Add frequently asked questions to this part too. Give users somewhere to turn to if they have problems.</li>
<li><strong>News</strong>: Front page should link to a couple of top news and at the bottom have link to a dedicated news-page with more info.</li>
<li><strong>Forum</strong>: Users should feel that this is a site with lots of people. Link to the topics in the forum most posted in to show them just that. This site is live and kicking.</li>
<li><strong>Search</strong>: Search might be important both if you look for either a poker term or for a feature on the site. Add search for both the forums and the news here and let people decide which of them to search.</li>
<li><strong>About us</strong>: Trust is important if you want people to part from their money. Put a picture of the staff online and quote reviews and happy customers (Don't fake this stuff. Never)</li>
<li><strong>Advertisement (Ads)</strong>: Ads need needs to be marked up as what they are. We want users to click on the ads only if they like the service the advertisers are serving</li>
</ul>
<p>We now need to transform this to HTML somehow. When you do this yourself, try to think as little about the color, fonts and such as possible. Focus on what <em>content</em> you want to show your users and build the HTML based on that.</p>
<p>On the next page we will get down to business and start coding. You want to see what I'm talking about don't you?</p>
<p>Time has come to go through the list of features and write the code for them. The question which we should keep in mind here is "What content do I have?".</p>
<h2 id="play-poker-button">Play poker button<a href="#play-poker-button">#</a></h2>
<p>Ok. We want a poker button. Some people prefer to use</p>
<p><code><input type="submit" /></code> for all kinds of buttons. Those buttons are made for submitting a form though, and that's not what we want here. When you think of it, is this "Play button" any different from a link? I think not. We will make it look like a button with CSS later on. Let's use the HTML of a simple link:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"play-poker.html"</span><span class="p">></span>Play poker<span class="p"></</span><span class="nt">a</span><span class="p">></span>
</pre></div>
<h2 id="advertisement">Advertisement<a href="#advertisement">#</a></h2>
<p>All sites cost money to run and getting that money is often done with some kind of advertisement on the site. What kind of ads should we use for this template? Looking at the top10 it seems that images are more common than text so let's use images. Don't forget to let advertisers specify alternate text to their images so you don't have to make something up for the alt attribute.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h2</span><span class="p">></span>Advertisement<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"url_to_advertisers_site.com"</span><span class="p">></span>
<span class="p"><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/play-roulette-online.png"</span> <span class="na">alt</span><span class="o">=</span><span class="s">"Advertisement: Play roulette online"</span> <span class="p">/></span>
<span class="p"></</span><span class="nt">a</span><span class="p">></span>
</pre></div>
<h2 id="beginners-guide">Beginners guide<a href="#beginners-guide">#</a></h2>
<p>To get beginners to play on our site we need to at least teach them the basics. How? People don't like manuals and they are often hard to navigate in. The best would be if no manual were needed at all, but let's be realistic, some people will still need help. A good approach is to use questions in natural language to lure people to read the guide. Keep it simple and easy to read. To mark that this is the beginners guide we add a header with that name in. Don't be tempted to use any other header than h2, the h1 will be used for the name of the site and this is a second level header, nothing else. To mark up the questions we use a paragraph of text with links. At the end we add a link to more information. The class "more" there is just a way to say that this paragraph is different from the one above.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h2</span><span class="p">></span>Beginners guide<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
If you are a poker beginner you might want to start by reading
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"help/rules-of-poker.html"</span><span class="p">></span>the rules<span class="p"></</span><span class="nt">a</span><span class="p">></span>. When you are done with that
you can <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#help/register.html"</span><span class="p">></span>register an account<span class="p"></</span><span class="nt">a</span><span class="p">></span> with us. Don't worry,
to join is free of charge and you can even win some money in our
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"help/monthly-tournaments.html"</span><span class="p">></span>monthly tournaments<span class="p"></</span><span class="nt">a</span><span class="p">></span>.
More questions are answered in the
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"help/frequently-asked-questions.html"</span><span class="p">></span>frequently asked questions<span class="p"></</span><span class="nt">a</span><span class="p">></span> section
</pre></div>
<h2 id="news">News<a href="#news">#</a></h2>
<p>People playing poker are probably interested in poker news too. By having news on your site your users don't have to go somewhere else looking for them. This will be a separate section so we should add a header here too, h2 is appropriate. The news items themselves are just items in an unordered list, so let's use the HTML for that, <code><ul></code>. End it all with a link to the news page that we wrap it in a classed paragraph like before.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h2</span><span class="p">></span>News<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>23 feb: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/highest-prize-ever"</span><span class="p">></span>Highest Prize Ever paid...<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>5 jan: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/caught-cheating"</span><span class="p">></span>Top player caught cheating<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>10 dec: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/how-to-improve"</span><span class="p">></span>How to improve your betting<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>1 nov: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/pokercompany-featured"</span><span class="p">></span>PokerCompany featured on...<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>30 okt: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/murkus-baltomi"</span><span class="p">></span>Murkus Baltomi the new...<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>24 apr: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"news/planned-downtime"</span><span class="p">></span>Planned downtime on Sunday<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
We maintain an <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#news/"</span><span class="p">></span>news archive<span class="p"></</span><span class="nt">a</span><span class="p">></span> too.
</pre></div>
<h2 id="forum">Forum<a href="#forum">#</a></h2>
<p>The forum posts can be handled much like the news. A header, a simple list, this time ordered by with the most active on top. End it with a now familiar classed paragraph.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h2</span><span class="p">></span>Forum<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=7"</span><span class="p">></span>Best strategy with one...<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 124 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=572"</span><span class="p">></span>Anyone know of a store...?<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 115 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=17"</span><span class="p">></span>What's the name of the...<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 89 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=67"</span><span class="p">></span>What your biggest pot?<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 51 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=23"</span><span class="p">></span>There was this guy in...<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 49 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"forum/forum.php?topic=325"</span><span class="p">></span>Help me get my...<span class="p"></</span><span class="nt">a</span><span class="p">></span> - 36 repl.<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#forum/"</span><span class="p">></span>Our forums<span class="p"></</span><span class="nt">a</span><span class="p">></span> are always filled with people to answer your questions.
</pre></div>
<h2 id="search">Search<a href="#search">#</a></h2>
<p>The bigger the site gets the more important it becomes to get a site search. A search clearly resembles a form; the user fills in a few values and sends them to the site. A simple textbox for the search query with a submit following it.</p>
<p>Just in case you're not familiar with the modern way to make a good form I'll go through the elements used below briefly.</p>
<p>A <code><fieldset></code> groups similar form elements together. For example, if you have two separate fields for first name and last name, you can signal that they are both part of the full name by adding a fieldset around both of them.</p>
<p>Using <code><legend></code> we then tell what the meaning of the fieldset is. For the previous example we could use "Full name".</p>
<p>The last "new" tag here is the <code><label></code>. It simply shows that there are a relation between the text in front of the button and the input box right next to it. A good thing about this relation is that it enables you to click on the label and have the input selected; something that is particularly useful with small radio buttons. This is what the HTML looks like:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">form</span> <span class="na">action</span><span class="o">=</span><span class="s">"search.php"</span> <span class="na">method</span><span class="o">=</span><span class="s">"get"</span><span class="p">></span>
<span class="p"><</span><span class="nt">fieldset</span><span class="p">></span>
<span class="p"><</span><span class="nt">legend</span><span class="p">></span>Site search<span class="p"></</span><span class="nt">legend</span><span class="p">></span>
<span class="p"><</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"phrase"</span><span class="p">></span>Search: <span class="p"></</span><span class="nt">label</span><span class="p">></span>
<span class="p"><</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">"text"</span> <span class="na">id</span><span class="o">=</span><span class="s">"phrase"</span><span class="p">></span>
<span class="p"><</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">"submit"</span> <span class="na">value</span><span class="o">=</span><span class="s">"search"</span><span class="p">></span>
<span class="p"></</span><span class="nt">fieldset</span><span class="p">></span>
<span class="p"></</span><span class="nt">form</span><span class="p">></span>
</pre></div>
<h2 id="about-us">About us<a href="#about-us">#</a></h2>
<p>Everyone wants to know who they're dealing with before they make a purchase of some kind (I believe that's one of the reasons some e-shops have problems, but that's a completely different story). Anyways, it's easy for you to put up an image and some quotes from people that are happy with your services, so do it. The header and "more" paragraph should be familiar by now.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h2</span><span class="p">></span>About us<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
PokerCompany has been in the business since 1997 and is...
Want to read <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"about/"</span><span class="p">></span>more about us<span class="p"></</span><span class="nt">a</span><span class="p">></span>?
</pre></div>
<p>On the next page we will take all the pieces of HTML and put them together. It's getting interesting, don't you think?</p>
<h2 id="what-a-structured-document-looks-like">What a structured document looks like<a href="#what-a-structured-document-looks-like">#</a></h2>
<p>We have carefully constructed all the markup for the important parts of the site. Notice that we've said nothing about the look of it yet, we’re strictly dealing with content.</p>
<p>We will first add all a good doctype (strict), character encoding and the other things needed for validation. I will not go over this again, it was described a couple of weeks ago in the <a href="/css/beginners-guide-to-css-and-standards/">beginner's guide</a>. This is just copy and paste, so don't skip this part.</p>
<p>Aside from that we also need to add some "hooks", namely classes and ids, to make it easier to style the document (If you don't know what those two are I recommend you read through the <a href="/css/beginners-guide-to-css-and-standards/">beginners guide</a> before continuing). Good class and id names have something in common: they describe the content. So using "tinyredbar" is a bad name and using "latestnews" is a good one.</p>
<p>The basics, the bits of HTML we constructed above and the hooks, together form a <a href="/files/poker/" data-no-instant>good logical structure</a> to start with. When looking at that page you will notice that it doesn't <em>look</em> pretty. When you view the source of it you will see though - that's what I want to see when I look at the source of your front page. I get all warm when thinking about it; pure, logical, and accessible content. It's now time to position things where we want them.</p>
<h2 id="apply-some-fancy-css">Apply some fancy CSS<a href="#apply-some-fancy-css">#</a></h2>
<p>For me the design part always starts with an image program of some sort (Macromedia Fireworks lately for its ease of use). After a while of fiddling around with images and colors I decided to go for something like <a href="/files/poker/poker-draft.jpg" data-no-instant>this draft</a> (Note that I'm a programmer rather than a designer so don't expect wonders here :).</p>
<p>When you site there with your image in front of you and are on your way to start with the CSS there is one thing you should remember: <em>do the positioning before you do the decoration</em>. The positioning is the hard part and it <strong>will</strong> get even harder if you start to mix in colors and fonts. Let's all follow what I just said and start with the positioning.</p>
<p>Think of every tag you have on your page as a little box. By <a href="/files/poker/?style=borders" data-no-instant>enabling borders</a> on all your elements you can get a good idea of what I'm talking about. When deciding how to position these boxes it's always wise to start to look at "the flow" of the document. The flow is what you just saw when you looked at the structure above, content is just stacked on top of each other and most tags occupy the full width. By using some clever combinations of floats, clears and widths/heights it is possible to things to line up like we want.</p>
<h2 id="positioning-the-header">Positioning the header<a href="#positioning-the-header">#</a></h2>
<p>Let's start by <a href="/files/poker/poker-draft.png" data-no-instant>looking at the top</a>. There seems to be four boxes here: a company name, company info, statistics, and the play button. The big image to the right can be added as a background, so we'll wait with that one. The first two boxes just need a smaller width to be where we want them (compare with how they where positioned in default flow). The last two ones need to be floated left and given a width (this will place them side by side).</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">h1</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">65</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">400</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">p</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">400</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">ul</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">130</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">header</span><span class="w"> </span><span class="nt">a</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">block</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">84</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">261</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<h2 id="positioning-the-navigation">Positioning the navigation<a href="#positioning-the-navigation">#</a></h2>
<p>Next up we will deal with the navigation and search. Start by adding <code>clear: both</code> to the navigation to make sure we are below any floats from earlier in the code. To make the navigation list horizontal we add <code>display: inline;</code> to all list items. We complete the navigation by setting a width on the list and floating it left.</p>
<p>The search box is a bit harder. All that info won't fit in the tiny space we have left so my idea is that we hide the fieldset, legend and label. "Why go through the fuzz of adding them and then hiding?", I hear you shout. Relax. They're there because they help users that surf the site with CSS turned off, people like your rich grandmother (using Netscape 4), blind users (using screen readers) and Google. Visual users still know that the textbox is for searching because of the "Search" on the button afterwards, so we're not hiding important information. Ohh, and the header won't fit our design either so let's hide that too.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">clear</span><span class="p">:</span><span class="w"> </span><span class="kc">both</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">41</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">720</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">ul</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="w"> </span><span class="k">list-style</span><span class="p">:</span><span class="w"> </span><span class="kc">none</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">400</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">li</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">inline</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">form</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">right</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">250</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">legend</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">label</span><span class="o">,</span><span class="w"> </span><span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">h2</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w"> </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">-10000</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">text-indent</span><span class="p">:</span><span class="w"> </span><span class="mi">-10000</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">line-height</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="nt">fieldset</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="kc">none</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<h2 id="positioning-the-advertisements">Positioning the advertisements<a href="#positioning-the-advertisements">#</a></h2>
<p>Ahhh, <acronym title="advertisements">ads</acronym>, both hated and loved at the same time. Not to include ads on a big site like this would just look strange. Let's position it like we want. First move it down below the navigation by clearing. Then float it right to get it out of the way from the content below.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">adverts</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">clear</span><span class="p">:</span><span class="w"> </span><span class="kc">both</span><span class="p">;</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">right</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<h2 id="positioning-the-content">Positioning the content<a href="#positioning-the-content">#</a></h2>
<p>This is going well; the content is next up for positioning. Note that I <a href="/files/poker/" data-no-instant>added a couple of divisions</a> to this part of the HTML when merging. They will come to good use now as holders of the four sections. Each of the boxes is given a specific width and height and gets floated left.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="nt">div</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">240</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Phew, this feels like a whole days work doesn't it? On the last page of this tutorial we will put all positioning together and show an example of how everything looks when decorated. Click next below.</p>
<h2 id="putting-it-all-together">Putting it all together<a href="#putting-it-all-together">#</a></h2>
<p>Now it's time to take all these small parts of CSS, put them in a CSS-file and <a href="/files/poker/?style=positioning" data-no-instant>apply it on the structure</a> we had before positioned. Can you <a href="/files/poker/positioning.css" data-no-instant>recognize the different parts</a> from the previous page?</p>
<p>I could bore you to death by explaining every little margin in the decoration step but I won't. Instead I will just show you the prettied up version of the site. You can have a look at the <a href="/files/poker/decoration.css" data-no-instant>second CSS file used</a> if you want.</p>
<p><strong><a href="/files/poker/?style=positioning&style2=decoration" data-no-instant>Final version of the site</a></strong></p>
<p>Let's have a look at the same properties we looked at in the beginning of this article:</p>
<table summary="A look at the web standards compliance of the template">
<tr>
<th>
Site name
</th>
<th>
Doctype
</th>
<th>
Validation errors
</th>
<th>
Layout method
</th>
</tr>
<tr>
<td>
Friendlybit template
</td>
<td class="correct">
Strict
</td>
<td class="correct">
0 errors
</td>
<td class="correct">
CSS
</td>
</tr>
</table>
<h2 id="summary">Summary<a href="#summary">#</a></h2>
<p>I hope this tutorial has showed you that CSS far from rocket science; could you not have done this yourself? The web really needs to be freshened up and made accessible for everyone, and with your help it can. Do your part by telling your friends, by holding a short presentation where you work, and by supporting webmaster you know work like this. Use your imagination, how can you make people understand?</p>
<p>Still here? Ok. If you're uncertain, ask yourself: can you afford to be left behind?</p>
<p>I hope this article gave you some insight to the development of a poker site. This article was the first is a series of articles about <a href="/css/building-niche-sites-with-standards/">niche templates</a> so be sure to check back for more. Any comments?</p>
Building niche sites with standards2006-01-23T03:30:56+01:002006-01-23T03:30:56+01:00http://friendlybit.com/css/building-niche-sites-with-standards/Emil StenströmI'm starting a new series of articles here at Friendly Bit. Through the use of web standards I will build a couple of niched sites and walk you through...
<p>I'm starting a new series of articles here at Friendly Bit. Through the use of web standards I will build a couple of niched sites and walk you through every step of the process. My hope is that this will make it easier for at least a few of you out there to understand what this web standards fuzz is all about. The use of web standards together with your creativity will make building websites fun again.</p>
<p>The first niche examined is <em>online poker</em>. The examination ended in a tutorial on <a href="/css/semantic-poker-template/">how to build a poker site</a>. What are you waiting for? Go read it!</p>
<p>My hope is that the templates will spread all the way to the niche markets they are made for. I appreciate any help with that. No matter what, I hope they will be great articles to learn from. Do you have anything to add? Use the comments.</p>
Line Breaking With Javascript2006-01-22T00:00:00+01:002006-01-22T00:00:00+01:00http://friendlybit.com/js/line-breaking-with-javascript/Emil StenströmOver the years there have been numerous suggestions of different ways of doing line breaks on the web. Browser incompatibilities, lack of support for...
<p>Over the years there have been numerous suggestions of different ways of doing line breaks on the web. Browser incompatibilities, lack of support for standardized features, and the creation of browser specific features all helps in making it incredibly difficult. Searching and reading for a while quickly brought me to think the best current solution is <a href="http://www.quirksmode.org/blog/archives/2005/06/quirks_mode_and_1.html">quirksmode's wbr</a>. It seems quite well supported but has two major flaws:</p>
<ol>
<li><code><wbr></code> is not valid HTML</li>
<li>The suggested solution does not work in Safari</li>
</ol>
<p>So off I went to find a better one. I started trying some different combinations of spaces marked up with <code><span></code> tags and I tried some nifty CSS tricks before it hit me - this should be done with javascript. Javascript has wide browser support and after some research (and help from the people in EFNet #javascript) I actually got a <a href="/files/js-linebreak/" data-no-instant>working example</a> up. I have been able to test it in FF 1.5/Win, IE 5.5/Win, IE 6/Win, Opera 8.51/Win+Mac, and Safari 2.0.3/Mac and everything seems to work fine in all of them.</p>
<h2 id="how-it-works">How it works<a href="#how-it-works">#</a></h2>
<p>The idea here is to add ordinary <code><br></code>s and using javascript to measure the length of the text. The user gives a piece of text and a width in pixels and the script returns the text with breaks inserted.</p>
<p>The hard part is to find at which letter we should break. My first idea was to just loop over the text and keep track of the width in pixels. When we get over the given width, back one step and add a break at that position. But this will be slow for small font-sizes and wide columns so let's do something faster. Instead of looping through all letters we can use <a href="http://en.wikipedia.org/wiki/Binary_search">Binary Search</a> (check the link if you're not familiar with it, it's good to know). This makes for a lot less calls.</p>
<p>We need a small change to the algorithm since we won't be able to find the exact width we're looking for (a letter is wider than 1px). Instead we break when we're down to knowing that it's between two letters. We then return the first letter's position. Here is code:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">binSearch</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span><span class="w"> </span><span class="nx">searchLen</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">lastBreakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="p">;</span>
<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">lastBreakPos</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">breakPos</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">lastBreakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">breakPos</span><span class="p">;</span>
<span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">((</span><span class="nx">left</span><span class="o">+</span><span class="nx">right</span><span class="p">)</span><span class="o">/</span><span class="mf">2</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">searchLen</span><span class="w"> </span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">text</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">breakPos</span><span class="p">)))</span>
<span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="nx">breakPos</span><span class="p">,</span><span class="w"> </span><span class="nx">lastBreakPos</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>The code above uses <code>getTextWidth()</code> to get the width of a piece of text. <code>getTextWidth()</code> makes use of the <code>offsetWidth</code> property to get the width of a piece of text. Problem is that only elements that are rendered have the property set. This means we need to add it to the page, measure it, and then remove it. This code does just that:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">ea</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s2">"span"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">ea</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">;</span>
<span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">ea</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ea</span><span class="p">.</span><span class="nx">offsetWidth</span><span class="p">;</span>
<span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">ea</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">len</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Good. We now have two nice helper functions to handle all the hard work. Now we only need some code to actually split the text and add the breaks. We do this by using <code>binSearch()</code> to fetch where the next break should be. <code>binSearch()</code> returns an index and we split the line and add the first part (including a break) to a buffer. We then repeat the same procedure on the last part of the string. We keep splitting until <code>getTextWidth()</code> tells us we're done.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">linebreak</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span><span class="w"> </span><span class="nx">maxLen</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">out</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">part1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">,</span><span class="w"> </span><span class="nx">part2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">part1</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">maxLen</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">getTextWidth</span><span class="p">(</span><span class="nx">part1</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">maxLen</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">breakPos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">binSearch</span><span class="p">(</span><span class="nx">part1</span><span class="p">,</span><span class="w"> </span><span class="nx">maxLen</span><span class="p">);</span>
<span class="w"> </span><span class="nx">part2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">part1</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">breakPos</span><span class="p">,</span><span class="w"> </span><span class="nx">part1</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="w"> </span><span class="nx">part1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">part1</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">breakPos</span><span class="p">);</span>
<span class="w"> </span><span class="nx">out</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">part1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w"> </span><span class="nx">part1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">part2</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">out</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">part2</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">text</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>It's now time to use the function we have. The first line selects what elements we want to wrap. You can replace this with a loop if you want if you need to go over all the paragraphs in your document. The second line just fetches everything inside the paragraph and sends it to <code>linebreak()</code> for wrapping. The two lines are then made to trigger when the document is ready loading.</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"p"</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">linebreak</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">,</span><span class="w"> </span><span class="mf">200</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>A <a href="/files/js-linebreak/" data-no-instant>working example</a> is available that shows what it can do. So, what do you think? Could this be the best solution so far to handling line breaks?</p>
Short web standards quiz2006-01-17T18:34:51+01:002006-01-17T18:34:51+01:00http://friendlybit.com/css/short-web-standards-quiz/Emil StenströmQ1. What does "semantics" mean in the context of web development? To use CSS for layout instead of tables To validate your page according to a given W3C...
<p class="first">
Q1. What does "semantics" mean in the context of web development?
</p>
<ol>
<li>To use CSS for layout instead of tables</li>
<li>To validate your page according to a given W3C specification</li>
<li>To use the most appropriate HTML tags for your content</li>
</ol>
<p class="first">
Q2. Which was the next CSS specification released after CSS2?
</p>
<ol>
<li>CSS3</li>
<li>CSS2.1</li>
<li>CSS2.0</li>
</ol>
<p class="first">
Q3. In context of content, presentation, and behaviour. What language is appropriate for the behaviour?
</p>
<ol>
<li>CSS</li>
<li>XHTML</li>
<li>Javascript</li>
</ol>
<p class="first">
Q4. If you want to mark that a certain word is short for something longer, which HTML tag should you use?
</p>
<ol>
<li><code><acronym></code></li>
<li><code><abbr></code></li>
<li><code><em></code></li>
</ol>
<p class="first">
Q5. Which of the following is NOT possible to do with W3C's CSS2?
</p>
<ol>
<li>Change the color of the scrollbar</li>
<li>Make a div fill the whole height of the page</li>
<li>Change the distance between lines of text in a paragraph</li>
</ol>
<p class="first">
Q6. One of the following is a valid doctype, which one?
</p>
<ol>
<li>HTML 4.01 Quirks mode</li>
<li>HTML 4 Standards mode</li>
<li>HTML 4.01 Strict</li>
</ol>
<p class="first">
Q7. W3C's validator (with XHTML 1.0 Transitional doctype) would let through one of the following lines. Which one?
</p>
<ol>
<li><code><adress>Sesame street 34Germany</adress></code></li>
<li><code><font color="red">Hello</font></code></li>
<li><code><em><table><tr><td>Data</td></tr></em></table></code></li>
</ol>
<p class="first">
Q8. The much awaited CSS3 specification includes the following feature:
</p>
<ol>
<li>An easy way to add shadows to your text</li>
<li>A way to open windows in new tabs</li>
<li>Possibility to animate (move) text and images</li>
</ol>
<p class="first">
Q9. Which of the following is valid CSS2?
</p>
<ol>
<li><code>display: inline-block;</code></li>
<li><span class="margin: 0; "><code>*</code></span></li>
<li><code>_width: 300px;</code></li>
</ol>
<p class="first">
Q10. Which of the following is NOT valid CSS2?
</p>
<ol>
<li><span class="font-size: 200%; "><code>p:first-letter</code></span></li>
<li><span class="width: 30ex; "><code>* html #container</code></span></li>
<li><span class="background: Silver; "><code>tr:nth-child(2n) td</code></span></li>
</ol>
<p>Are you uncertain about any of the questions? Just post a comment and I'll answer. (You can also use the comments just to show off or points out errors of course :).</p>
Cross browser CSS for your site2006-01-13T00:21:39+01:002006-01-13T00:21:39+01:00http://friendlybit.com/css/cross-browser-strategies-for-css/Emil StenströmThis article will go through some useful cross-browser CSS techniques I use to get my sites to look the same in several modern browsers. It's fairly easy to...
<p>This article will go through some useful cross-browser CSS techniques I use to get my sites to look the same in several modern browsers. It's fairly easy to send out different versions of your site to different browsers. This should be avoided though since it will end up with you having to maintain the site as if it was in fact several. That defeats the whole purpose with standards, why are they even needed if you are adapting to the browsers instead? My opinion is that good cross-browser coding is to find the set of standards that <em>are</em> supported and then use them.</p>
<h2 id="validate">Validate your site<a href="#validate">#</a></h2>
<p>Validation is a much debated area and many <a href="/css/levels-of-css-knowledge/">Level 2 bosses</a> doubt that this procedure really helps. It does help though. It ensures that you didn't do any simple spelling errors, things that could be incredibly hard to find manually. A validator also checks for nesting errors (did you put a <code><div></code> inside of an anchor?) and other strange things like your character encoding. Information about each of the errors is available as links when they appear, just click on one and you're on your way to learn something new.</p>
<p>Validation is the simplest of my tricks to check. There are validators available for both <a href="http://validator.w3.org/">(X)HTML</a> and <a href="http://jigsaw.w3.org/css-validator/">CSS</a>. Use them! Any errors that show up on those lists could be a potential cross-browser breaker so if you decide to ignore any of them you should be really sure about what you are doing. There are reasons why each one of all of the errors on the validation page show up, so validate, fix, validate, fix, validate.</p>
<h2 id="mode">Stay in standards mode<a href="#mode">#</a></h2>
<p>The next trick is not as obvious. Modern browsers have two rendering modes they use to display websites with: <em>Standards mode</em> and <em>Quirks mode</em>. Standards mode is a rendering mode that is made to work according to the W3C specifications as closely as possible and Quirks mode is a bug ridden mode made for older sites. Why have a mode with bugs you ask? It's a way for browser makers to keep their users happy. When you do big changes to your rendering engine a lot of old sites relying on browser bugs will break. Some might think that this is a good thing, why should sites still work when they are poorly coded? If you think like that you have forgot about who the web is for. It's not a place for experts only, it's made for regular users, that is, <em>anyone</em> with a browser. Those people need to see a working site if that's possible.</p>
<p>So a new browser is released with a more standards compliant rendering mode and pages start to break. This is a bad thing for users so browser makers decided to first identify pages that tried to follow the standards, and if they did, switch to the new and improved rendering mode. You will probably see why I recommend standards mode now. All browsers are trying to render things as similar to the specs as possible when in standards mode, while in quirks mode they keep all their old bugs just to help regular users.</p>
<p>So how do the browsers identify who's trying to follow standards and who's not? They use the <em>doctype</em>. If you're not familiar with doctypes, don't worry, they are easy to learn. A doctype is a tag on first line of your site file telling the browser what markup language you will be using. There are basically two doctypes you should select among:</p>
<p><strong>HTML 4.01 Strict (what I recommend)</strong></p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="cp"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"></span>
</pre></div>
<p><strong>XHTML 1.0 Strict (without <code><?xml ...></code> on the line before)</strong></p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="cp"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"></span>
</pre></div>
<p>Using any of these make sure the browser switches to standards mode and your design not fail because of that. Using a <em>strict</em> doctype means that you will do your best to separate structure from design and the validator will give you errors in those areas. It's very useful. (Worth a small note is that the XHTML Transitional doctype also triggers standards mode, but while using transitional you don't get as many good validation checks so don't use that one anyways.)</p>
<p>There is one last catch one needs to talk about when dealing with doctypes and standards mode - <strong>the doctype needs to be the first tag in the document</strong>. If you put any HTML comments or strange characters before it <acronym title="Internet Explorer">IE</acronym> will go crazy and switch to quirks mode. This has cause many developers countless hours of trying to fix things. Just don't do it!</p>
<h2 id="default">Remove default styling of elements<a href="#default">#</a></h2>
<p>Another cause of many web developers screaming in the night is the default CSS that is applied to elements. If you don't use any CSS at all on your page elements will still have a certain look. Headers will be larger than text paragraphs and blockquotes will have padding. Sizes of text is something that is pretty similar across browsers but something that's not is padding and margins. Let me give you an example: With no styling an <code><ul></code> gets a padding in Firefox but a margin in IE. Solution? Set either the margin or padding to zero and set the other one to the indentation you want. You need to somehow remove the default browset styles.</p>
<p>These kinds of problems take up a lot of development time if not handled nicely. "Do definition lists in Opera have padding or margin?". "What about second level headers in IE 6?". Two schools of thought have evolved to handling this. The first one tells you to start by resetting <em>all</em> margins to their defaults at the top of you CSS file. This can easily be done by typing in <span class="margin: 0; padding: 0; "><code>*</code></span>, * being a <a href="http://css.maxdesign.com.au/selectutorial/selectors_universal.htm">universal selector</a> that applies the same rules to <em>all</em> elements.</p>
<p>Problem solved right? That's where the second school of thought comes in. They argue that too many default margins are reset. Why should we mess with users form fields, rendering them hard to use unless they are set to good values again? Instead you could just reset those elements that have differences, and leave the rest untouched. This is quite a lot of work to get right so Faruk Ate? built a "starting css" template that you can easily include in your head. Personally I prefer the *-method, but try both and decide for yourself.</p>
<h2 id="bugs">Browser bugs<a href="#bugs">#</a></h2>
<p>This is the area where CSS gets hard. Even though browser makers work their asses off to follow standards they sometimes don't reach their goals. This leaves us webmasters with bugs that when fixed triggers new bugs, either in the same or another browser. It can easily get real dirty.</p>
<p>One of the worst browsers (that is widely in use) is Microsoft's Internet Explorer, version 6. Some claim they have about 80% of the browser market so it's not a browser you can just ignore. IE was a good browser when it was first released but by today's standards it's certainly not. No other browser caused me more pain while building the design of this page. Its shortcomings get painfully clear when it comes to rendering complex CSS layouts.</p>
<p>How do you handle these bugs then? The easiest (and fastest) way is not solving it yourself but reading up on someone else's solution. "Holly 'n John" have gathered the most frequent bugs on their page <a href="http://positioniseverything.net/explorer.html">Explorer Exposed!</a>. They give you examples of how to detect the bug, how it works and why (sometimes) and most importantly how to solve it. Sometimes the solution is just setting <code>position: relative;</code> or <code>display: inline;</code> on some element and sometimes you have to resort to strange code. The point here is that if your bug is on that page; don't waste time trying to figure it out yourself. Learn that list by heart.</p>
<p>So what do you do if your bug isn't on the list? You start by googling for a solution of course. Googling takes a few minutes compared to the hour you probably need to hunt it down. Don't underestimate this step.</p>
<p>If you don't find it somewhere you need to hunt it down yourself. Do this by making a copy of your page and then removing as much code as you can while keeping the bug. Then find out exactly what line (or lines) of code that causes it and finally try to find another way of doing what triggers it. This is much better than just throwing in hacks, you keep your code maintainable and you learn a lot more useful stuff than if you were throwing in nonsense code from the beginning.</p>
<p>If you for some reason do not manage to solve the bug with the above technique you either rethink what you are doing (not likely) or you go get your arsenal of hacks. Make sure the hacks are valid code. The one I use for IE when nothing else works is the "* html" hack. You use it but writing like this: <span class="code; "><code>* html #element</code></span>. That selector selects all tags that have the child html that have the child #element. But "html" is the topmost element in the hierarchy so nothing is selected, unless IE can choose of course. The code gets applied in IE only. Note that it is perfectly valid CSS, it just doesn't select anything. Remember: hacks are your <em>last resort</em> when nothing else works.</p>
<p><strong>Update 18 Jan:</strong> <a href="#comment-51">Richard</a> in the comments point out that you can also use <a href="http://www.quirksmode.org/css/condcom.html">conditional comments</a> to serve a certain <code><style> or <link></code> to different versions of IE. The "* html"-hack will not work in the comming IE7. Thanks Richard.</p>
<p> </p>
<p>I hope you found something useful in this article that you can use when you get cross-browser CSS problems. I have now told you what steps I use, did I miss something? Do you do something differently?</p>
Happy Birthday Me!2006-01-12T11:04:36+01:002006-01-12T11:04:36+01:00http://friendlybit.com/other/happy-birthday-me/Emil StenströmIt seems I got 24 years old. I wonder when that happened? After some research I found that 24 is a pretty good number after all.
<p>It seems I got 24 years old. I wonder when that happened? After some research I found that 24 is a <a href="http://richardphillips.org.uk/number/Num24.htm" title="Information about the number 24">pretty good number</a> after all.</p>
Levels of CSS knowledge2006-01-11T01:25:29+01:002006-01-11T01:25:29+01:00http://friendlybit.com/css/levels-of-css-knowledge/Emil StenströmAs you might have understood by now I'm very much pro web standards. The current widely accepted standards are: (X)HTML for page structure, CSS for design,...
<p>As you might have understood by now I'm very much pro web standards. The current widely accepted standards are: (X)HTML for page structure, CSS for design, and Javascript for behaviour. HTML is pretty well known by now, it has been there since the beginning of the web and there are tutorials everywhere that gets you started. CSS is starting to get a grip, large companies are switching their sites to CSS based layouts and the webdev blogosphere reaches more and more people.</p>
<p>When you promote web standards, like many of us do, you get to talk to a lot of people. If you promote it in a live chat room like #CSS on EFNet it gets even clearer: there are a lot of different levels of CSS knowledge out there. This article is going to list some of those levels along a rating of how this kind of developer will affect the web. Here we go:</p>
<h2 id="level-0">Level 0<a href="#level-0">#</a></h2>
<blockquote>
<p>"CSS? Isn’t that a multiplayer game?"</p>
</blockquote>
<p>These people have probably never made a webpage in their life. If they did it was pure HTML and they barely knew what they were doing. We get some of these people in #CSS, not because they want to start learning but because they think they've come to another channel, often looking for <acronym title="Counter-Strike: Source">CS:S</acronym>. No need to worry about these people, they probably won't do many webpages in their lives so they can't do much harm.</p>
<h2 id="level-1">Level 1<a href="#level-1">#</a></h2>
<blockquote>
<p>"Yeah, I use it to remove underlines on links sometimes"</p>
</blockquote>
<p>Different from Level 0, the people in this level do actually know basic HTML. They probably learned it at least five years ago and have made a couple of simple sites. They use very little CSS, only when they need to do simple stuff you can't do with HTML only, like removing underlines and setting line-height (No! don't even think about setting line-height with HTML). While these people could present us with some badly coded sites they rarely have any large and well visited ones. This means that they won't do much harm either.</p>
<h2 id="level-2">Level 2<a href="#level-2">#</a></h2>
<blockquote>
<p>"No, I don't like divs; tables are much easier to work with"</p>
</blockquote>
<p>Instead of just playing with HTML, like those from Level 1, some continued their quest. They mastered HTML tables and started using it to make things look just like they wanted. Somewhere around reaching HTML mastery they stopped looking at new ways of working. They heard about other people using "divs to design their pages" and even took some time one day to try to learn what the fuss was about. After a few hours of not getting it they gave up, went back to the familiar land of tabled layouts, and stayed there. Many do know CSS syntax and sometimes even some background but they believe it's far too hard and ill-supported to use instead of tables.</p>
<p>Watch it! These are dangerous people, some even webmasters of big corporate websites. Since they have been in the business for a while many are leaders for their web departments. These are the people it's most important to reach, and if we do it means a lot for the web. Concentrate on these people all you standards advocates.</p>
<h2 id="level-3">Level 3<a href="#level-3">#</a></h2>
<blockquote>
<p>"Yes I've heard it's good, but I can't use it because of…"</p>
</blockquote>
<p>While people in this group still don't use CSS for positioning they do know some CSS and perhaps heard good things about it. They've tried making simple layouts and some even liked how it felt to work with. Problem here is that something is stopping them. Perhaps they have a Level 2 boss, perhaps their website needs to cater for Netscape 4 users, there might be many different reasons but something is in the way.</p>
<p>These people need to know that while CSS <em>does not</em> work everywhere that isn't the end of the world. Old browsers will still get all your content, just pure content. Instead of them you will reach a new audience: there may be accessibility and usability benefits, newer browsers will get a <em>richer</em> experience and the site might even get easier to add content to (which will lead to more content). Tell this to the people in this group. If you're unlucky they are not be the ones making decisions but in that case their influence on Level 2 Bosses will still be worth it.</p>
<h2 id="level-4">Level 4<a href="#level-4">#</a></h2>
<blockquote>
<p>"CSS? Oh! Yes, I use divs for all my layouts"</p>
</blockquote>
<p>It's not unusual that these people use only divs on their sites. Each part of their page gets a div, often with a carefully crafted id (#toprightredline or even #r5_c7 with r standing for row and c for column), and then they position their divs with absolute positioning by the pixel. The result looks good, hey, it even validates as XHTML 1.1(!) but what they have missed is that most of the benefits of CSS has been lost. These pages are terrible when it comes to a screen reader interpreting it. Same with older non-CSS browsers, they won't get the content… they will get one big block of text. When using bad class names and ids you loose the possibility to change the layout: if that red line needs to be changed to black you'll need to change all your HTML documents too (can be hundreds). Don't fall into the trap of telling them they are stupid or make them google "css", they know they are smart people and they did learn about CSS from google in the first place. Tell them exactly what could be improved on their sites. Tell them what the benefits are. Keep your cool and tell them <em>why</em>.</p>
<p>People of Level 4 produce sites that are rather bad. The damage is reduced though by them often being open to new ideas. After all, not to long ago they did manage to learn and start to use CSS.</p>
<p>Some of the reasons for people thinking this way is because of what <acronym title="What You See Is What You Get">WYSIWYG</acronym> editors are doing. Most such editors produce terrible div-only code but I'm hearing that there are gradual improvements in this field. This is a good thing and hopefully this will help people move from Level 4 to the higher levels.</p>
<h2 id="level-5">Level 5<a href="#level-5">#</a></h2>
<blockquote>
<p>"I use CSS for design, it's better than tables because of…"</p>
</blockquote>
<p>After a lot of reading, talking to people and thinking most people arrive at Level 5. This is where you both <em>can use</em> CSS and <em>know why</em> it's better. Some people in this level have minor problems on the sites they produce but it's nothing serious. When asked they can argue why separating structure and design is a good thing and they have worked with CSS long enough to know the common pitfalls. I'm guessing many of the readers of this article are on this level and I feel I am. But this is not the best we can do…</p>
<h2 id="level-6">Level 6<a href="#level-6">#</a></h2>
<blockquote>
<p>"What version of CSS? Yes, I do. Did you read my book about…"</p>
</blockquote>
<p>For some people knowing how and why isn't enough. These people strive to improve how CSS is used and are publishing great articles on new ways of using it. They constantly go back to the basic needs CSS is filling and attack problems from new angles, often resulting in more great articles. Some have actually read the whole W3C specification on CSS (sic) and they certainly know which parts are supported by which browsers. They function as role models for beginners and do great things for the web with their influence. Many work with the <a href="http://webstandards.org">Web Standards Project</a>. If you ever find an error on their site there is a reason for it. Ask them and they'll tell you why.</p>
<p> </p>
<p class="first">
That's it. I hope this article gave you some inspiration to keep pushing the web to new victories. At which level are you? Do you have examples of people in last level?
</p>
Simple CSS templates2006-01-07T16:25:48+01:002006-01-07T16:25:48+01:00http://friendlybit.com/css/simple-css-templates/Emil StenströmThe most frequent question in the #CSS channel I'm in is about how you make a 2 column layout. Most beginners seems to have problems understanding how...
<p>The most frequent question in the #CSS channel I'm in is about how you make a 2 column layout. Most beginners seems to have problems understanding how floats work since they are quite different from tables. So I sat down and made some simple layout templates for you. These layouts will all be made with floats since that's the easiest way to do things. I could have set out to use absolute positioning but that can get tricky when it comes to placing the footer. Let's stay with floats.</p>
<p>I'll recap how a floats work. A float is applied by simply setting <code>float: left</code> or <code>float: right</code> on an element in your CSS-file. The element then gets pushed as far to the left or right as possible and the next element will follow to the right (if floated left) or left (if floated right). The closest HTML comparision is the effect you get when setting align="left" on an image. In the beginning it helped me to think of floats like that.</p>
<p>There are basically two ways to make 2 column layouts with floats. Either you float all the columns (float-float) or you float all but the last one (float-margin). The former method makes it easier to work with clearing inside of the second columns though, so if you're going for a complex layout float-float might be better. The latter has the advantage that you don't have to set a width on the last column. It will fill whatever space is availiable. My favourite is still float-margin though, the automatically expanding second column makes sure the the full width is used no matter what.</p>
<p>For the examples below I will use the HTML I outlined in my previous article about <a href="/css/beginners-guide-to-css-and-standards/">CSS basics</a>.</p>
<h2 id="the-float-margin-method">The float-margin method<a href="#the-float-margin-method">#</a></h2>
<p>Let's start by looking at some examples:</p>
<ul>
<li><a href="/files/templates/?style=2columns_float_margin" data-no-instant>2 columns using float-margin</a></li>
<li><a href="/files/templates/?style=3columns_float_float_margin&cols=3" data-no-instant>3 columns using float-margin</a></li>
</ul>
<p>Ok, so how does this work? The first example: The navigation is floated left which means that the next element will follow to the right of it. This sounds right but we are forgetting one thing, what happens if the navigation is very short? Then the text in the right column will continue <a href="/files/templates/float_example.html" data-no-instant>below the float</a>, probably not what we wanted. So, to fix this we add a margin-left to our content division. Voilà!</p>
<p>The 3 column example is based on the same idea. Here we start by floating the navigation left, floating the first content block right and finally add margins to the second content block. The last block needs to have both a margin-left and a margin-right to stop the text from continuing below the left and right columns. Makes sense? Take a look at the code and I hope it will.</p>
<h2 id="the-float-float-method">The float-float method<a href="#the-float-float-method">#</a></h2>
<p>Another method of doing the same is floating each of the columns left. This means that the columns will show up on the webpage in the same order as you put them in the HTML (that was <em>not</em> the case in the previous example, content1 was to the right and content2 in the middle). Some examples for you:</p>
<ul>
<li><a href="/files/templates/?style=2columns_float_float" data-no-instant>2 columns using float-float</a></li>
<li><a href="/files/templates/?style=3columns_float_float_float&cols=3" data-no-instant>3 columns using float-float</a></li>
<li><a href="/files/templates/?style=4columns_float_float_float_float&cols=4" data-no-instant>4 columns using float-float</a></li>
</ul>
<p>There isn't much explaination needed here, only thing different from the float-margin method is that you need to set a width on all your columns. You should easily be able to expand this method to kazillion columns :)</p>
<p>That's all, be sure to poke around with the different layouts to get a feel of how they work for you. In my next post I will go through some less static layouts, namely elastic and fluid layout. Comments are availiable for questions.</p>
<blockquote>
<p><strong>Update</strong>: Added an article on <a href="/css/what-beginners-ask-for-and-what-i-tell-them/">Common questions beginners ask</a></p>
</blockquote>
Make a tooltip out of some columns in a table2006-01-06T01:16:59+01:002006-01-06T01:16:59+01:00http://friendlybit.com/css/make-a-tooltip-out-of-some-columns-in-a-table/Emil StenströmA worried user joins the #CSS channel on EFNet. He has a big problem with the site he's currently working on and wonders if there might be a problem with...
<p>A worried user joins the #CSS channel on EFNet. He has a big problem with the site he's currently working on and wonders if there might be a problem with his markup. Let's see what he wants.</p>
<p>The site sells some kind of houses and each house has a few "options" (let's pretend a bigger door is one option) that the user should be able to select among. Each of these options has a name and costs a certain amount of money. When you move your mouse over one of the options, he wants more info to pop up in a small box. In the box there should be an image, a store name and strange number. What HTML should he use to mark that up?</p>
<p>We talked for a while and thought about definition lists containing a div with the extra info in, perhaps a two-column table with a div in the second column? After looking again it became pretty clear, if we just look at his data and not think about the design, all that was left was one big table. Everything that he wants in the tooltip are things that could as well be shown in a big table. So why not use exactly that markup and then use javascript to make some cells only pop up when the row was hovered?</p>
<p>This is the markup I propose:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">table</span> <span class="na">summary</span><span class="o">=</span><span class="s">"Options for your house"</span><span class="p">></span>
<span class="p"><</span><span class="nt">thead</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Option<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span><span class="p">></span>Price<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip"</span><span class="p">></span>Image<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip"</span><span class="p">></span>Store<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"><</span><span class="nt">th</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip"</span><span class="p">></span>SKU#<span class="p"></</span><span class="nt">th</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">thead</span><span class="p">></span>
<span class="p"><</span><span class="nt">tbody</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Bush<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>$3<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a1"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/bush.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">"An alabama bush"</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a2"</span><span class="p">></span>Alabama<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a3"</span><span class="p">></span>#23535151<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>Bush<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">></span>$3<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a1"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"/files/post-media/bush.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">"An alabama bush"</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a2"</span><span class="p">></span>Alabama<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span> <span class="na">class</span><span class="o">=</span><span class="s">"tooltip a3"</span><span class="p">></span>#23535151<span class="p"></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"></</span><span class="nt">tbody</span><span class="p">></span>
<span class="p"></</span><span class="nt">table</span><span class="p">></span>
</pre></div>
<p>What you see there is a plain five column table with some classes spread out to make it easier to fetch what we want with the javascript later on. The whole table is given the id "info", this makes us able to separate it from other tables on the same page. Each cell that are going to be in the tooltip get the class "tooltip" and an aditional a1-a3 class that simply is used to position the specific cell later on.</p>
<p>Next we need to do two of things:</p>
<ol>
<li>Loop over the table and hide everything with the class "tooltip"</li>
<li>Loop over all table rows and add a mouseover function to each of them that makes them show all hidden cells in that particular row</li>
</ol>
<p>To fetch all elements that has a certain className we will use Jonathan Snook's fabulous getElementsByClassName. It takes two arguments, the element whose children it should loop through and the className it should look for. The function looks like this:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="kd">function</span><span class="w"> </span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span><span class="w"> </span><span class="nx">classname</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">re</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">RegExp</span><span class="p">(</span><span class="s1">'\\b'</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">classname</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">'\\b'</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">els</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">node</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"*"</span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="o">=</span><span class="mf">0</span><span class="p">,</span><span class="nx">j</span><span class="o">=</span><span class="nx">els</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">ij</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nx">re</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">els</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">className</span><span class="p">))</span><span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">els</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">a</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Next we need to write the code that fulfils the list we wrote previously:</p>
<div class="highlight" data-language="JS"><pre><span></span><span class="c1">// Hide all classes with the className "tooltip"</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">tooltips</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getElementsByClassName</span><span class="p">(</span>
<span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"body"</span><span class="p">)[</span><span class="mf">0</span><span class="p">],</span><span class="w"> </span><span class="s2">"tooltip"</span><span class="p">);</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="nx">tooltips</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">tooltips</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">className</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s2">" hide"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">tbodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"tbody"</span><span class="p">);</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">tbodies</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">trows</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">tbodies</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s2">"tr"</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// Add a function to each tr that makes it show it's cells on mouseover</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">trows</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">trows</span><span class="p">[</span><span class="nx">j</span><span class="p">].</span><span class="nx">onmouseover</span><span class="o">=</span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">childtooltips</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="s2">"tooltip"</span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">childtooltips</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">childtooltips</span><span class="p">[</span><span class="nx">k</span><span class="p">].</span><span class="nx">className</span><span class="o">+=</span><span class="s2">" hooover"</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// And hides all child cells on mouseout</span>
<span class="w"> </span><span class="nx">trows</span><span class="p">[</span><span class="nx">j</span><span class="p">].</span><span class="nx">onmouseout</span><span class="o">=</span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">childtooltips</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="s2">"tooltip"</span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">childtooltips</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">childtooltips</span><span class="p">[</span><span class="nx">k</span><span class="p">].</span><span class="nx">className</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="nx">childtooltips</span><span class="p">[</span><span class="nx">k</span><span class="p">].</span><span class="nx">className</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="ow">new</span><span class="w"> </span><span class="nb">RegExp</span><span class="p">(</span><span class="s2">" hooover\\b"</span><span class="p">),</span><span class="w"> </span><span class="s2">""</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>A note here is that we don't loop over the first table row. That one contains the table headers and shouldn't react to us hovering it.</p>
<p>Last but not least we need a few lines of CSS to make the page behave like we want it to. Without either Javascript or CSS enabled a plain table should be shown with all cells visible. If you have both enabled you don't want the cells that contain the tooltip to take up space in the table. Here's the code:</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="p">.</span><span class="nc">hide</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">-10000</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">hooover</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">80</span><span class="kt">px</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="nt">tr</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">relative</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">.</span><span class="nc">a1</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">px</span><span class="w"> </span><span class="kc">solid</span><span class="w"> </span><span class="n">Black</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">300</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">a2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">padding</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="kt">px</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">120</span><span class="kt">px</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">.</span><span class="nc">a3</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">padding</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="kt">px</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">200</span><span class="kt">px</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
<p>The "hide" class is added to any element with the class "tooltip". Why not make the tooltip class hide the cells right away you ask? The answer is that then a non js user would not see those cells at all. This way we get the best of both worlds. To remove the hidden cells from taking up space we remove them from the flow with <code>position: absolute;</code> and to hide them we use <code>left: -10000px</code>.</p>
<p>The "hooover" class get enabled when we mouseover one of the table rows. It just sets the left value to a far more visible 100px. Lastly we set some styles on the a1-a3 classes that makes the tooltip look a little better. We use a1 as a background and place the other two classes on top of it to make it look like they are in the same box.</p>
<p>And that's it, a <a href="/files/table-tooltip/" data-no-instant>table turned into a tooltip</a>, another user is a little bit happier and all would be fine... Unless of course the user had left the channel before I could show him my solution. Damn.</p>
Beginner’s guide to CSS2006-01-05T18:11:00+01:002006-01-05T18:11:00+01:00http://friendlybit.com/css/beginners-guide-to-css-and-standards/Emil StenströmIn the chat channel I'm in, I get to talk to people on a daily basis that have never used CSS before, or are at the very beginning of learning it.. This...
<p>In the chat channel I'm in, I get to talk to people on a daily basis that have never used <acronym title="Cascading StyleSheets">CSS</acronym> before, or are at the very beginning of learning it.. This article teaches all the basics you need to make your first CSS powered website. It is aimed at people that know a little <acronym title="HyperText Markup Language">HTML</acronym>, and maybe have made a few websites themselves. Let's get started.</p>
<h2 id="what">What is CSS?<a href="#what">#</a></h2>
<p>CSS is a language that adds style (colors, images, borders, margins…) to your site. It's really that simple. CSS is not used to put any content on your site, it's just there to take the content you have and make it pretty. First thing you do is link a CSS-file to your HTML document. Do this by adding this line:</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span> <span class="na">href</span><span class="o">=</span><span class="s">"style.css"</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/css"</span><span class="p">></span>
</pre></div>
<p>The line should be placed in between your <code><head></code> tags. If you have several pages you could add the exact same line to all of them and they will all use the same stylesheet, but more about that later. Let's look inside the file "style.css" we just linked to.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">h1</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mi">40</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">warning</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="kc">red</span><span class="p">;</span>
<span class="w"> </span><span class="k">font-weight</span><span class="p">:</span><span class="w"> </span><span class="kc">bold</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">footer</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background-color</span><span class="p">:</span><span class="w"> </span><span class="kc">gray</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>You have three <dfn>selectors</dfn> up there, <code>h1</code>, <code>.warning</code> and <code>#footer</code>. A selector simply points to somewhere in your HTML document. It can be built in many ways and can be a combination of the following building blocks:</p>
<ul>
<li>Element</li>
<li>Class</li>
<li>Id</li>
</ul>
<p>I'm going to go through all three of them and explain what they do.</p>
<p>An <dfn>element</dfn> points at a HTML-tag somewhere on your page. In the example above we want to style the <code><h1></code>-tag. Note that using an element like that affects all tags with that name, so using <span class="margin-left: 100px; "><code>p</code></span> gives <em>all</em> <code>p</code>-tags a left-margin.</p>
<p>Using a <dfn>class</dfn> is just as simple. When writing <code>.your_class</code> you style all tags with a class with the name "your_class". In the example above we have <code>.warning</code> which will style e.g. <code><div class="warning"></code> and <code><em class="warning"></code>, that is, any element with the class warning. Classes are used when you want to style just a few of your tags in a way, perhaps you want some of your links red? Add a class to all those links.</p>
<p>You need one more building block: the <dfn>id</dfn>. This time you style an element with the attribute "id" set to the id you have chosen. Ids work exactly like classes except for one thing; you can only have one id with a certain name in each of your HTML documents. In the example above we style <code><div id="footer"></code>. If you look at the example it does make sense: a HTML document may contain several warnings but only one footer. Ids should be used when you want to style just one specific tag.</p>
<p>Using those three building blocks will take you far but when you get to more advanced layouts you might want to combine the building blocks into more advanced selectors. Just to give you two examples of what you can do: <code>em.warning</code> to style only those <code><em></code>-tags with the class <code>.warning</code> set. You can also use <code>#footer a</code> to style only the links that are nested inside the tag with id "footer". Pretty nice, isn't it?</p>
<p>I could go on forever about the advanced uses of selectors but this is a beginner tutorial so I won't. If you want all the finer details, go have a look at the excellent <a href="http://css.maxdesign.com.au/selectutorial/">Maxdesigns Selectutorial</a>.</p>
<p>Let's go on explaining the code above. Each of the selectors has a set of <dfn>declarations</dfn> tied to them. Each declaration has a <dfn>property</dfn>, describing what we want to change and a <dfn>value</dfn>, what we should change it to. Too many terms there? Are you still with me? Let me explain with an example: <span class="color: Blue; font-size: 3em; "><code>a</code></span>. You have the <dfn>selector</dfn> <code>a</code> there, so all links in your document will be styled. We have two <dfn>declarations</dfn>: <code>color: Blue</code> and <code>font-size: 3em;</code>. Lastly each declaration consists of two parts: the <dfn>property</dfn> <code>color</code> and the <dfn>value</dfn> <code>Blue</code>. Phew! Well done for making it this far. The terms above are good to know since it gives you a way to talk about your CSS. If you join a CSS-channel asking for help with your code and they tell you "You have an error in your a-selector in the second declaration" you know exactly where! Right? :)</p>
<p>Now you will probably ask what properties there are. You have seen <code>font-size</code> and <code>color</code> but what else is there? The answer is that there are a <em>LOT</em> of things you can style and play with. Additionally (close to) all tags are equal in CSS, so you can set e.g. borders and colors of <em>any</em> element just like you could with a table if you used only HTML. Starting to see the possibilities?</p>
<p>I won't go through all the properties here, it would just bore you to death. Instead I'll point you to another great resource: <a href="http://www.w3schools.com/css/">w3schools section about CSS</a>. Just select one of the menu options to the left to start exploring what CSS can do.</p>
<p>But don't you leave me all alone here, there is more to learn! Next we will talk about good and bad coding and there will be a lot of colorful examples for you. Sounds good?</p>
<h2 id="separation">CSS is all about separation<a href="#separation">#</a></h2>
<p>One of the least followed parts of CSS is the very idea behind it, the idea of separation of content and design. The idea here is that all sites contain two major parts, the content: all your articles, text and photos and the design: rounded corners, colors and effects. Usually those two are made in different parts of a webpage's lifetime. The design is determined at the beginning and then you start filling it with content and keep the design fixed. So if you just want to add content to your site you don't want to be forced to mess around with the design, do you? The same thing is true the other way around, if you decide on a redesign, why should you have to mess around with the content, making sure it fits in the new layout?</p>
<p>In CSS you just add the nifty <code><link></code>-tag I've told you about to the head of your HTML document and you have created a link to your design. In the HTML document you put content only, and that link of yours makes sure it looks right. You can also use the exact same link on many of your pages, giving them all of them the same design. You want to add content? Just write a plain HTML document and think about marking things up like "header" instead of "big blue header" and use CSS to make <em>all</em> headers look the way you want!</p>
<p>This is a different way of thinking about webpages, and it's something that took a while for me to understand. To help you I have written some examples of good and bad coding. What's wrong with this?</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">font</span> <span class="na">size</span><span class="o">=</span><span class="s">"3"</span><span class="p">></span>Welcome to my page<span class="p"></</span><span class="nt">font</span><span class="p">></span>
</pre></div>
</div><p>Comment: The font-tag is design and design shouldn't be in the HTML document. All design should be in the CSS-file! Instead do this:</p>
<p>In the HTML:</p>
<div class="correct"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">h1</span><span class="p">></span>Welcome to my page<span class="p"></</span><span class="nt">h1</span><span class="p">></span>
</pre></div>
</div><p>In the CSS:</p>
<div class="correct"><div class="highlight" data-language="CSS"><pre><span></span><span class="nt">h1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">font-size</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="kt">em</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
</div><p>One more example:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">b</span><span class="p">></span>An error occurred<span class="p"></</span><span class="nt">b</span><span class="p">></span>
</pre></div>
</div><p>Comment: This looks right doesn't it? But if you look up what <code><b></code> stands for you quickly find <em>bold</em>. But bold is certainly design, so it still doesn't belong in the HTML document. A better choice is <code><em></code> that stands for <em>emphasis</em> or simply "this piece of text is important". So instead of saying "this text looks like this" you are saying "this text is important" and you let the looks be decided by the CSS. Seems like a minor change, but it illustrates how to select your tags. Use this instead:</p>
<p>In the HTML:</p>
<div class="correct"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">em</span><span class="p">></span>An error occured<span class="p"></</span><span class="nt">em</span><span class="p">></span>
</pre></div>
</div><p>In the CSS:</p>
<div class="correct"><div class="highlight" data-language="CSS"><pre><span></span><span class="nt">em</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">font-weight</span><span class="p">:</span><span class="w"> </span><span class="kc">bold</span><span class="p">;</span>
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="n">Red</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div><p>One last example:</p>
<div class="incorrect"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">table</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span><span class="p">></span>first link<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">tr</span><span class="p">></span>
<span class="p"><</span><span class="nt">td</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span><span class="p">></span>second link<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">td</span><span class="p">></span>
<span class="p"></</span><span class="nt">tr</span><span class="p">></span>
...
<span class="p"></</span><span class="nt">table</span><span class="p">></span>
</pre></div>
</div><p>Comment: Lots of people format their navigation menu like the above example. But is a navigation menu really a table? If you look up the definition of a table you see that it's made for tabular data, the same kind of data you would put in an Excel sheet. The example has only one column of data, and no headers… Some people state that they use tables because that means that they can get borders and a background color on their navigation, but that's exactly what your CSS file is for (not the HTML document). So what should we do? Look deep in the list of <a href="http://www.w3schools.com/html/">HTML elements at w3schools</a> and you'll find something called an unordered list, <code><ul></code>. Have a look at this:</p>
<p>In the HTML:</p>
<div class="correct"><div class="highlight" data-language="HTML"><pre><span></span><span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span><span class="p">></span>first link<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span><span class="p">></span>second link<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
...
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
</pre></div>
</div><p>In the CSS:</p>
<div class="correct"><div class="highlight" data-language="CSS"><pre><span></span><span class="nt">li</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">px</span><span class="w"> </span><span class="kc">solid</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div><p>This is probably a different way of thinking about HTML than you're used to but trust me, when you've worked with it for a while you'll see the power of it. Not only does this way of coding give you a more logical structure, there is also proof that this improves your ranking in search engines and makes it easier for accessibility devices to read your site. This way of designing is great.</p>
<p>Next we will build a simple HTML template to use as a start when building a new page. Like to see it?</p>
<h2 id="building-a-standards-based-html-template">Building a standards based HTML template<a href="#building-a-standards-based-html-template">#</a></h2>
<p>We have talked a lot about the theory behind CSS and HTML working together to form a site with good structure that is separated from the design. But the first parts of building pages are always the same, you type</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="cp"><!doctype html></span>
<span class="p"><</span><span class="nt">html</span><span class="p">></span>
<span class="p"><</span><span class="nt">body</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="cm"><!-- Header here! --></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"navigation"</span><span class="p">></span>
<span class="cm"><!-- Navigaiton here! --></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"content"</span><span class="p">></span>
<span class="cm"><!-- Content here --></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">body</span><span class="p">></span>
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
</pre></div>
<p>Ok, there might be some new stuff there so let's go through the lines one by one. First we state this document's doctype: what language we use. You might have heard of XHTML, another similar web language, but for a first page we don't need the features that gives us access to, keep it simple, just go with HTML. Also, the <code><!doctype html></code> above sets the document to use <em>Strict</em> HTML. To understand that you need to know that there are two kinds of rendering in a browser. One that follows the standards set up by the <a href="http://www.w3c.org">W3C</a>, <dfn>"standards mode"</dfn>, and one for older pages, called <dfn>"quirks mode"</dfn>. Standards mode is what we want to use. It makes the pages render (almost) the same in modern browsers and it frees us from being dependent on a specific browser, we'll just follow the standard. Quirks mode is something of a bug mode. It's there to keep old pages looking the same as they did before browsers started trying to follow the standards and is therefore intentionally filled with strange bugs. A browser determines which rendering mode to use based on what doctype we use, so make sure you use the right one!</p>
<p>Ok. That's a lot of explaining for a single line of code, I'll be swifter now, next line. You have probably written <code><html></code> before in the beginning of your documents. My line is almost like that except that I have added <code>lang="en"</code> there. That line tells the browser which language we will use. Why does it matter what language we use? you ask… Well, there is assistive technology that read webpages to people out loud called screen readers. Those <em>have to</em> know what language it is to be able to pronounce the words. It's so easy for you to add those few characters so why not do it? If you don't plan on making an English page you can find your own language code by visiting <a href="http://www.w3.org/WAI/ER/IG/ert/iso639.htm#2letter">WAIs Language Codes</a> and check out the two-letter names there (<em>Note:</em> language codes are in lowercase).</p>
<p>Next we have the <em>head</em> of the document. The head contains a some of meta-information about the page, like character encoding, title and what stylesheet (CSS file) to use. The charset there is the trickiest one so let's take that first. There are a lot of different letters in a language. When computers where first constructed the engineers only thought about the American/English language, they didn't even think about the swedish letters å, ä, ö or the deutsch umlaut ü or what about the &-sign? There are a lot of characters and at first there was no general consensus on how to handle them. Then someone came up with the smart idea of grouping them into <em>sets</em>, groups of characters that are used in certain parts of the world. So, what the meta-tag does is simply to state: "This person wants to input western characters (latin-1 characters)", and this tells the browser what character set to use. A more genaral approach is to use the utf-8 character set but that quickly gets tricky. Finally we have a text/html there that simply tells the server to send the document as a HTML, not like an image or something like that. The <code><title></code> and <code><link></code> you should be familiar with, if not, google it :)</p>
<p>That was a lot of info on just a few lines of code, I hope I didn't give the impression that this stuff is hard, because it's not. To use the stuff above you just copy and paste it and start filling it with content.</p>
<p>The body of the document consists of a bunch of divisions, let's add some content to them:</p>
<div id="semantics"></div>
<div class="highlight" data-language="HTML"><pre><span></span>...
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h1</span><span class="p">></span>The name of this page<span class="p"></</span><span class="nt">h1</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"navigation"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span>Navigation<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"first.html"</span><span class="p">></span>First<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"second.html"</span><span class="p">></span>Second<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"third.html"</span><span class="p">></span>Third<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"content"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span>Content<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
Some sample content, add your own here
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"footer"</span><span class="p">></span>
This page is written by [Your name] and builds on a <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://friendlybit.com"</span><span class="p">></span>Friendlybit template<span class="p"></</span><span class="nt">a</span><span class="p">></span>.
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
...
</pre></div>
<p>What have we done here? First you should note that a quick overview of the document tells you quite much about the content. You can easily see that some stuff are headers (h1, h2) and some are just a list of links (ul, li, a). Let's go through the code quickly:</p>
<p>First we have a header. A header is something that's most often a big image and some text. Some pages don't have the header in the HTML at all, they just link to an image and have the text in that image. Problem with that is that neither search engines nor screen readers can get the title text. With the title text being the most important piece of description a visitor has to what page they have come to, you do have a problem. So trust me, keep that text there.</p>
<p>Next up we have the navigation. Navigation should almost always be marked up as an unordered list of links. I've seen the strangest variants of this with tables, nested tables, ``-tags after each line and so on but the only content there is a list of links, why make it something it isn't? Using a list doesn't mean it will have to look a certain way, remember that all design is handled in the CSS later on, this is just HTML we are dealing with here. Note: you can easily remove the bullet marks with <code>list-style: none;</code>, that's not a reason to use some other HTML.</p>
<p>The most important part of your HTML document is the content. This is the reason people will visit your page and this is where you should put most of your effort. Mark your headers with appropriate header-tags and make sure they look different from the ordinary text, this makes it easier quickly get a grip of what you're are trying to say. Use paragraph tags around your paragraphs to make is easier to style your text. The CSS <code>text-indent: 2em;</code> adds some space before only the first word in each paragraph, just to name one simple thing you can do with CSS when you've used good markup.</p>
<p>Lastly, it could be a good idea to add a footer to your page. Make sure you have some kind of contact information here or somewhere else on your site, who knows what people will want to ask you? If you want to help me you could add a link to this site somewhere on your site too. If you do, thanks alot!</p>
<p>On the next (and last) page of this short beginners guide we will wrap everything up and add some sample CSS to the mix. All is free for you to copy and use on your page. Ready?</p>
<h2 id="full-html-template-and-sample-css">Full HTML template and sample CSS<a href="#full-html-template-and-sample-css">#</a></h2>
<p>Let's start by putting the two pieces of HTML I showed you together and combine it with some sample CSS: <a href="/files/example1/" data-no-instant>Sample HTML + CSS</a>. You can find all code that makes that page below. Feel free to copy the code below and experiment on your own.</p>
<div class="highlight" data-language="HTML"><pre><span></span><span class="cp"><!doctype html></span>
<span class="p"><</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">"en"</span><span class="p">></span>
<span class="p"><</span><span class="nt">body</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h1</span><span class="p">></span>The name of this page<span class="p"></</span><span class="nt">h1</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"navigation"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span>Navigation<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"first.html"</span><span class="p">></span>First<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"second.html"</span><span class="p">></span>Second<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"third.html"</span><span class="p">></span>Third<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"content"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span>Content<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
Some sample content, add your own here
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"footer"</span><span class="p">></span>
This page is written by [Your name] and builds on a <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://friendlybit.com"</span><span class="p">></span>Friendlybit template<span class="p"></</span><span class="nt">a</span><span class="p">></span>.
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">body</span><span class="p">></span>
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
</pre></div>
<p>You should be able to tell what each part of the HTML does by now. Let's instead have a look at some sample CSS for the structure we have above. If you want to experiment with this code you can copy it to a file named style.css (or any other filename you reference in the <code><link></code>-tag in the HTML) and place it in the same directory as the HTML document.</p>
<div class="highlight" data-language="CSS"><pre><span></span><span class="nt">body</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">background-color</span><span class="p">:</span><span class="w"> </span><span class="n">Green</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">div</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="kt">px</span><span class="w"> </span><span class="kc">solid</span><span class="w"> </span><span class="n">Black</span><span class="p">;</span>
<span class="w"> </span><span class="k">padding</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">600</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">h1</span><span class="o">,</span><span class="w"> </span><span class="nt">h2</span><span class="o">,</span><span class="w"> </span><span class="nt">h3</span><span class="o">,</span><span class="w"> </span><span class="nt">h4</span><span class="o">,</span><span class="w"> </span><span class="nt">h5</span><span class="o">,</span><span class="w"> </span><span class="nt">h6</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">margin</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">navigation</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">150</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">content</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">float</span><span class="p">:</span><span class="w"> </span><span class="kc">left</span><span class="p">;</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">430</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">#</span><span class="nn">footer</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">clear</span><span class="p">:</span><span class="w"> </span><span class="kc">both</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Let's go through the six rules above. First we set the background-color of body, and body is the background of everything, so this will do the same as bgcolor did in HTML.</p>
<p>Next we set some styles on all divisions on the page. We have four of them and with this single rule we affect them all. First we set a black border to be 3 pixels wide (note that there is no space between number and unit in CSS). We then set a padding (the space between the border and content) to be 7 pixels and lastly we set the width of all divs to 600 pixels (note that margins, borders and padding are not included in the width).</p>
<p>The third rule selects all headers on the page and removes the margins (the space between the border and other nearby elements) from them. The commas are used between the elements to apply the same CSS to all of them.</p>
<p>Next we have some specific rules for three of the divisions. We position the navigation to the left of the content. This is done by using <dfn>floats</dfn>, a way to put things side by side. If you have used the align-attribute on images in HTML you will know how floats work, they move the element as far to the left as possible and then let the next element follow right next to it. If you want to put something below a float you need to <dfn>clear</dfn> it. Clearing moves the element down until it's below any floats, exactly where we want the footer. So both navigation and content are floated and given a width to match the 600 pixels wide header, and the footer is cleared.</p>
<p><strong>Update:</strong> I have added some <a href="/css/simple-css-templates/">simple layouts</a> for you to look at, and a list of <a href="/css/web-development-pack/">tools I use when developing</a>. Hope they help all of you out there that learn by examples.</p>
<p>Now it's your turn, you will learn CSS by using it and trying out how things work. So go ahead and play with the sample above. Thanks for reading, and good luck!</p>
<p>Any ideas of how this guide could be improved? Just leave a comment to the right.</p>
Julrim 20052005-12-24T00:00:21+01:002005-12-24T00:00:21+01:00http://friendlybit.com/other/christmas-riddles-for-2005/Emil StenströmJag tänkte det kunde vara kul för några av er att se mina julrim för i år. Jag bestämde mig för att använda Limerick-form, mest för att en stor tidning hade...
<p>Jag tänkte det kunde vara kul för några av er att se mina julrim för i år. Jag bestämde mig för att använda Limerick-form, mest för att en stor tidning hade en rolig ramsa som jag gillade.</p>
<blockquote>
<p>Man tänker på bad och långa stränder<br /> Man använder denna i dessa länder<br /> båd långa och smala<br /> och mat för koala<br /> det knaprar i användarn's tänder</p>
</blockquote>
<blockquote>
<p>Randig el. rutig man oftast den ser<br /> på lillbroshans axlar när han sig beger<br /> till vänner på fest<br /> på klubb som en gäst<br /> med dessa jag hoppas han ler</p>
</blockquote>
<blockquote>
<p>Färgen på dessa är oftast ju vit<br /> paketet från detta avviker en bit<br /> Man på sig dem har<br /> alen el. i par<br /> och bäraren han bli elit</p>
</blockquote>
<blockquote>
<p>Du lutar dig fram och lägger mot öra<br /> en bomb, men kan du något tickande höra?<br /> av händer rätt små<br /> båd lila och blå<br /> Vad är det? Kan du det avgöra?</p>
</blockquote>
<p>Sorry again for the bit of swedish there. So, can you guess what's inside or if you wrote your own riddle, would you mind posting it in the comments to the left? Merry Christmas to you all!</p>
How this website was built2005-12-20T00:00:36+01:002005-12-20T00:00:36+01:00http://friendlybit.com/css/how-this-website-was-built/Emil StenströmHi there early readers! Welcome to a newly started web development blog. I know that there are a lot of those around so I will work hard to make it...
<p>Hi there early readers! Welcome to a newly started web development blog. I know that there are a lot of those around so I will work hard to make it different and hopefully earn your trust. This site will mainly consist of new stuff; very few of those “news about news” posts, there are better places for that. “Web development” I say, and by that I most often will mean client side techniques like HTML, CSS and Javascript. This is the idea and I hope it will work out.</p>
<p>This site has been worked on for over a year so it's about time I get it up and working. This article will talk mostly about how this site has been built. You will hopefully notice that to me it's important that you practice what you preach.</p>
<h2 id="wordpress-as-backbone">WordPress as backbone<a href="#wordpress-as-backbone">#</a></h2>
<p>I'm running the blog software WordPress 2.0 as the base for all this. I've read a lot of good things about it and I know PHP so I thought why not give it a try? In just a week I had written my own theme and a few plug-ins to go with it. WordPress really is well built and easy to use. Any problems I've had have been answered in the IRC help-channel by nice people. Kudos to the WordPress team for doing a great job.</p>
<h2 id="fireworks-for-building-the-idea">Fireworks for building the idea<a href="#fireworks-for-building-the-idea">#</a></h2>
<p>All my layouts start out in Macromedia Fireworks. Fireworks is a nice program to work in even though I'm not used to their other programs. I have tried Photoshop but it just didn't work out between us. Floating toolboxes? Startup time that makes me fall to sleep? No, I wanted something that’s easy to get started with, and if possible something that had special tools for web development. Fireworks is perfect for this, it’s like a combination of Illustrator and Photoshop and has a user interface that even a beginner learns quickly.</p>
<p>I played with a few different layouts until I found something I liked. The idea with this one is to put the content in focus. Everything except the content column is dark so the white will stick out. The text starts a bit above the text in the left column and has a big <code><h1></code> so you know where to start. The comments are placed in the sidebar, mostly because there probably will be very few in the beginning. Don't take that as an insult, I want to hear what you say, but this is not a forum or wiki :)</p>
<h2 id="css-elastic-faux-columns-for-implementing-it">CSS elastic faux columns for implementing it<a href="#css-elastic-faux-columns-for-implementing-it">#</a></h2>
<p>This site does not use tables for layout (of course!). I'm an operator of a help channel for CSS so that would be unacceptable :) A lot of work has gone to make sure the layout works like it should.</p>
<p>The layout in Fireworks was complete and I had the hard part left, converting my mock-up to a web site. After many tries I finally decided to go with a zoomable layout. I know this is hard to work with, especially with complex sites like this one but I thought I’d give it a try. Worked out pretty well I think. The biggest bug I know of is that the header look strange in Opera and Safari, as far as I can understand it's because of a bug in both their rendering engines when calculating percentages. Anyhow, the site works well in both Internet Explorer 6 and Firefox so I hope most of you will see it like it's meant to.</p>
<p>The layout is made zoomable by using the em unit on the parent container. When text-zooming (Ctrl + Plus in Firefox and View -> Text Size in <acronym title="Internet Explorer">IE</acronym>) the em unit adjusts to what you select so everything gets nice. There is one big problem with changing text-size though: images do not change size when you text-zoom. So certain parts of the site need to stay fixed and some need to move for the site not to collapse.</p>
<p>I wanted background-images in all my three columns so having all columns change their sizes started to look hard. Then I stumbled over an article about faux columns that used percentages to position a background-image so that it could grow in both directions. The faux columns technique uses a repeating background-image to fake columns. By using two of those images I could get it working on a 3 column layout with percentages.</p>
<p>The next step was making the site zoomable. If I set the container to a fixed em width and then use faux columns with percentages throughout the site I get what I want. Everything worked out and I could start working in the small parts. Want to see how much trouble IE gave me? Just have a look in my "decoration" stylesheet, I commented every browser problem I encountered in IE, Opera and FF and solved most of them :)</p>
<h2 id="miscellaneous">Miscellaneous<a href="#miscellaneous">#</a></h2>
<p>All images used are from <a href="http://www.sxc.hu">SXC.hu</a>, the excellent stock image directory. Highly recommended.</p>
<p>That's it people, my site and the idea behind it. I hope you will come back and read my articles. Thanks for reading.</p>