{"rowid": 318, "title": "Auto-Selecting Navigation", "contents": "In the article Centered Tabs with CSS Ethan laid out a tabbed navigation system which can be centred on the page. A frequent requirement for any tab-based navigation is to be able to visually represent the currently selected tab in some way.\n\nIf you\u2019re using a server-side language such as PHP, it\u2019s quite easy to write something like class=\"selected\" into your markup, but it can be even simpler than that.\n\nLet\u2019s take the navigation div from Ethan\u2019s article as an example.\n\n
\n\nAs you can see we have a standard unordered list which is then styled with CSS to look like tabs. By giving each tab a class which describes it\u2019s logical section of the site, if we were to then apply a class to the body tag of each page showing the same, we could write a clever CSS selector to highlight the correct tab on any given page. \n\nSound complicated? Well, it\u2019s not a trivial concept, but actually applying it is dead simple.\n\nModifying the markup\n\nFirst thing is to place a class name on each li in the list:\n\n \n\nThen, on each page of your site, apply the a matching class to the body tag to indicate which section of the site that page is in. For example, on your About page:\n\n...\n\nWriting the CSS selector\n\nYou can now write a single CSS rule to match the selected tab on any given page. The logic is that you want to match the \u2018about\u2019 tab on the \u2018about\u2019 page and the \u2018products\u2019 tab on the \u2018products\u2019 page, so the selector looks like this:\n\nbody.home #navigation li.home,\n body.about #navigation li.about,\n body.work #navigation li.work,\n body.products #navigation li.products,\n body.contact #navigation li.contact{\n ... whatever styles you need to show the tab selected ...\n } \n\nSo all you need to do when you create a new page in your site is to apply a class to the body tag to say which section it\u2019s in. The CSS will do the rest for you \u2013 without any server-side help.", "year": "2005", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2005-12-10T00:00:00+00:00", "url": "https://24ways.org/2005/auto-selecting-navigation/", "topic": "code"} {"rowid": 319, "title": "Avoiding CSS Hacks for Internet Explorer", "contents": "Back in October, IEBlog issued a call to action, asking developers to clean up their CSS hacks for IE7 testing. Needless to say, a lot of hubbub ensued\u2026 both on IEBlog and elsewhere. My contribution to all of the noise was to suggest that developers review their code and use good CSS hacks. But what makes a good hack?\n\nTantek \u00c7elik, the Godfather of CSS hacks, gave us the answer by explaining how CSS hacks should be designed. In short, they should (1) be valid, (2) target only old/frozen/abandoned user-agents/browsers, and (3) be ugly. Tantek also went on to explain that using a feature of CSS is not a hack.\n\nNow, I\u2019m not a frequent user of CSS hacks, but Tantek\u2019s post made sense to me. In particular, I felt it gave developers direction on how we should be coding to accommodate that sometimes troublesome browser, Internet Explorer. But what I\u2019ve found, through my work with other developers, is that there is still much confusion over the use of CSS hacks and IE. Using examples from the code I\u2019ve seen recently, allow me to demonstrate how to clean up some IE-specific CSS hacks.\n\nThe two hacks that I\u2019ve found most often in the code I\u2019ve seen and worked with are the star html bug and the underscore hack. We know these are both IE-specific by checking Kevin Smith\u2019s CSS Filters chart. Let\u2019s look at each of these hacks and see how we can replace them with the same CSS feature-based solution.\n\nThe star html bug\n\nThis hack violates Tantek\u2019s second rule as it targets current (and future) UAs. I\u2019ve seen this both as a stand alone rule, as well as an override to some other rule in a style sheet. Here are some code samples:\n\n* html div#header {margin-top:-3px;}\n.promo h3 {min-height:21px;}\n* html .promo h3 {height:21px;}\n\nThe underscore hack\n\nThis hack violates Tantek\u2019s first two rules: it\u2019s invalid (according to the W3C CSS Validator) and it targets current UAs. Here\u2019s an example:\n\nol {padding:0; _padding-left:5px;}\n\nUsing child selectors\n\nWe can use the child selector to replace both the star html bug and underscore hack. Here\u2019s how:\n\n Write rules with selectors that would be successfully applied to all browsers. This may mean starting with no declarations in your rule!\n\ndiv#header {}\n.promo h3 {}\nol {padding:0;}\n\n \nTo these rules, add the IE-specific declarations.\n\ndiv#header {margin-top:-3px;}\n.promo h3 {height:21px;}\nol {padding:0 0 0 5px;}\n\n \nAfter each rule, add a second rule. The selector of the second rule must use a child selector. In this new rule, correct any IE-specific declarations previously made.\n\ndiv#header {margin-top:-3px;}\nbody > div#header {margin-top:0;}\n\n.promo h3 {height:21px;}\n.promo > h3 {height:auto; min-height:21px;}\n\nol {padding:0 0 0 5px;}\nhtml > body ol {padding:0;}\n\n \n\nVoil\u00e0 \u2013 no more hacks! There are a few caveats to this that I won\u2019t go into\u2026 but assuming you\u2019re operating in strict mode and barring any really complicated stuff you\u2019re doing in your code, your CSS will still render perfectly across browsers. And while this may make your CSS slightly heftier in size, it should future-proof it for IE7 (or so I hope). Happy holidays!", "year": "2005", "author": "Kimberly Blessing", "author_slug": "kimberlyblessing", "published": "2005-12-17T00:00:00+00:00", "url": "https://24ways.org/2005/avoiding-css-hacks-for-internet-explorer/", "topic": "code"} {"rowid": 313, "title": "Centered Tabs with CSS", "contents": "Doug Bowman\u2019s Sliding Doors is pretty much the de facto way to build tabbed navigation with CSS, and rightfully so \u2013 it is, as they say, rockin\u2019 like Dokken. But since it relies heavily on floats for the positioning of its tabs, we\u2019re constrained to either left- or right-hand navigation. But what if we need a bit more flexibility? What if we need to place our navigation in the center?\n\nStyling the li as a floated block does give us a great deal of control over margin, padding, and other presentational styles. However, we should learn to love the inline box \u2013 with it, we can create a flexible, centered alternative to floated navigation lists.\n\nHumble Beginnings\n\nDo an extra shot of \u2018nog, because you know what\u2019s coming next. That\u2019s right, a simple unordered list:\n\n \n\nIf we were wedded to using floats to style our list, we could easily fix the width of our ul, and trick it out with some margin: 0 auto; love to center it accordingly. But this wouldn\u2019t net us much flexibility: if we ever changed the number of navigation items, or if the user increased her browser\u2019s font size, our design could easily break.\n\nInstead of worrying about floats, let\u2019s take the most basic approach possible: let\u2019s turn our list items into inline elements, and simply use text-align to center them within the ul:\n\n#navigation ul, #navigation ul li {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n#navigation ul {\n text-align: center;\n}\n\n#navigation ul li {\n display: inline;\n margin-right: .75em;\n}\n\n#navigation ul li.last {\n margin-right: 0;\n}\n\nOur first step is sexy, no? Well, okay, not really \u2013 but it gives us a good starting point. We\u2019ve tamed our list by removing its default styles, set the list items to display: inline, and centered the lot. Adding a background color to the links shows us exactly how the different elements are positioned.\n\nNow the fun stuff.\n\nInline Elements, Padding, and You\n\nSo how do we give our links some dimensions? Well, as the CSS specification tells us, the height property isn\u2019t an option for inline elements such as our anchors. However, what if we add some padding to them?\n\n#navigation li a {\n padding: 5px 1em;\n}\n\nI just love leading questions. Things are looking good, but something\u2019s amiss: as you can see, the padded anchors seem to be escaping their containing list.\n\nThankfully, it\u2019s easy to get things back in line. Our anchors have 5 pixels of padding on their top and bottom edges, right? Well, by applying the same vertical padding to the list, our list will finally \u201ccontain\u201d its child elements once again.\n\n\u2019Tis the Season for Tabbing\n\nNow, we\u2019re finally able to follow the \u201cSliding Doors\u201d model, and tack on some graphics:\n\n#navigation ul li a {\n background: url(\"tab-right.gif\") no-repeat 100% 0;\n color: #06C;\n padding: 5px 0;\n text-decoration: none;\n}\n\n#navigation ul li a span {\n background: url(\"tab-left.gif\") no-repeat;\n padding: 5px 1em;\n}\n\n#navigation ul li a:hover span {\n color: #69C;\n text-decoration: underline;\n}\n\nFinally, our navigation\u2019s looking appropriately sexy. By placing an equal amount of padding on the top and bottom of the ul, our tabs are properly \u201ccontained\u201d, and we can subsequently style the links within them.\n\n\n\nBut what if we want them to bleed over the bottom-most border? Easy: we can simply decrease the bottom padding on the list by one pixel, like so.\n\nA Special Note for Special Browsers\n\nThe Mac IE5 users in the audience are likely hopping up and down by now: as they\u2019ve discovered, our centered navigation behaves rather annoyingly in their browser. As Philippe Wittenbergh has reported, Mac IE5 is known to create \u201cphantom links\u201d in a block-level element when text-align is set to any value but the default value of left. Thankfully, Philippe has documented a workaround that gets that [censored] venerable browser to behave. Simply place the following code into your CSS, and the links will be restored to their appropriate width:\n\n/**//*/\n#navigation ul li a {\n display: inline-block;\n white-space: nowrap;\n width: 1px;\n}\n/**/\n\nIE for Windows, however, displays an extra kind of crazy. The padding I\u2019ve placed on my anchors is offsetting the spans that contain the left curve of my tabs; thankfully, these shenanigans are easily straightened out:\n\n/**/\n* html #navigation ul li a {\n padding: 0;\n}\n/**/\n\nAnd with that, we\u2019re finally finished.\n\nAll set.\n\nAnd that\u2019s it. With your centered navigation in hand, you can finally enjoy those holiday toddies and uncomfortable conversations with your skeevy Uncle Eustace.", "year": "2005", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2005-12-08T00:00:00+00:00", "url": "https://24ways.org/2005/centered-tabs-with-css/", "topic": "code"} {"rowid": 332, "title": "CSS Layout Starting Points", "contents": "I build a lot of CSS layouts, some incredibly simple, others that cause sleepless nights and remind me of the torturous puzzle books that were given to me at Christmas by aunties concerned for my education. However, most of the time these layouts fit quite comfortably into one of a very few standard formats. For example:\n\n\n\tLiquid, multiple column with no footer\n\tLiquid, multiple column with footer\n\tFixed width, centred\n\n\nRather than starting out with blank CSS and (X)HTML documents every time you need to build a layout, you can fairly quickly create a bunch of layout starting points, that will give you a solid basis for creating the rest of the design and mean that you don\u2019t have to remember how a three column layout with a footer is best achieved every time you come across one! \n\nThese starting points can be really basic, in fact that\u2019s exactly what you want as the final design, the fonts, the colours and so on will be different every time. It\u2019s just the main sections we want to be able to quickly get into place. For example, here is a basic starting point CSS and XHTML document for a fixed width, centred layout with a footer.\n\n \n\n\nSidebar content here
\nYour main content goes here.
\n\n\n\nNotice that you can\u2019t just put the quoted text directly between theProgressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.
\n
tags. In order for your markup to be valid, block quotes may only contain block-level elements such as paragraphs.\n\nThere is an optional cite attribute that you can place in the openingtag. This should contain a URL containing the original text you are quoting:\n\n\n\n\nGreat! Except\u2026 the default behavior in most browsers is to completely ignore the cite attribute. Even though it contains important and useful information, the URL in the cite attribute is hidden.\n\nYou could simply duplicate the information with a hyperlink at the end of the quoted text:\n\nProgressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.
\n\n\n\nBut somehow it feels wrong to have to write out the same URL twice every time you want to quote something. It could also get very tedious if you have a lot of quotes.\n\nWell, \u201ctedious\u201d is no problem to a programming language, so why not use a sprinkling of DOM Scripting? Here\u2019s a plan for generating an attribution link for every block quote with a cite attribute:\n\n\n\tWrite a function called prepareBlockquotes.\n\tBegin by making sure the browser understands the methods you will be using.\n\tGet all the blockquote elements in the document.\n\tStart looping through each one.\n\tGet the value of the cite attribute.\n\tIf the value is empty, continue on to the next iteration of the loop.\n\tCreate a paragraph.\n\tCreate a link.\n\tGive the paragraph a class of \u201cattribution\u201d.\n\tGive the link an href attribute with the value from the cite attribute.\n\tPlace the text \u201csource\u201d inside the link.\n\tPlace the link inside the paragraph.\n\tPlace the paragraph inside the block quote.\n\tClose the for loop.\n\tClose the function.\n\n\nHere\u2019s how that translates to JavaScript:\n\nfunction prepareBlockquotes() {\n if (!document.getElementsByTagName || !document.createElement || !document.appendChild) return;\n var quotes = document.getElementsByTagName(\"blockquote\");\n for (var i=0; iProgressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.
\n\n source\n
\ntags.\n\nYou can style the attribution link using CSS. It might look good aligned to the right with a smaller font size.\n\nIf you\u2019re looking for something to do to keep you busy this Christmas, I\u2019m sure that this function could be greatly improved. Here are a few ideas to get you started:\n\n\n\tShould the text inside the generated link be the URL itself?\n\tIf the block quote has a title attribute, how would you take its value and use it as the text inside the generated link?\n\tShould the attribution paragraph be placed outside the block quote? If so, how would you that (remember, there is an insertBefore method but no insertAfter)?\n\tCan you think of other instances of useful information that\u2019s locked away inside attributes? Access keys? Abbreviations?", "year": "2005", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2005-12-05T00:00:00+00:00", "url": "https://24ways.org/2005/dom-scripting-your-way-to-better-blockquotes/", "topic": "code"} {"rowid": 326, "title": "Don't be eval()", "contents": "JavaScript is an interpreted language, and like so many of its peers it includes the all powerful eval() function. eval() takes a string and executes it as if it were regular JavaScript code. It\u2019s incredibly powerful and incredibly easy to abuse in ways that make your code slower and harder to maintain. As a general rule, if you\u2019re using eval() there\u2019s probably something wrong with your design.\n\nCommon mistakes\n\nHere\u2019s the classic misuse of eval(). You have a JavaScript object, foo, and you want to access a property on it \u2013 but you don\u2019t know the name of the property until runtime. Here\u2019s how NOT to do it:\n\nvar property = 'bar';\nvar value = eval('foo.' + property);\n\nYes it will work, but every time that piece of code runs JavaScript will have to kick back in to interpreter mode, slowing down your app. It\u2019s also dirt ugly.\n\nHere\u2019s the right way of doing the above:\n\nvar property = 'bar';\nvar value = foo[property];\n\nIn JavaScript, square brackets act as an alternative to lookups using a dot. The only difference is that square bracket syntax expects a string.\n\nSecurity issues\n\nIn any programming language you should be extremely cautious of executing code from an untrusted source. The same is true for JavaScript \u2013 you should be extremely cautious of running eval() against any code that may have been tampered with \u2013 for example, strings taken from the page query string. Executing untrusted code can leave you vulnerable to cross-site scripting attacks.\n\nWhat\u2019s it good for?\n\nSome programmers say that eval() is B.A.D. \u2013 Broken As Designed \u2013 and should be removed from the language. However, there are some places in which it can dramatically simplify your code. A great example is for use with XMLHttpRequest, a component of the set of tools more popularly known as Ajax. XMLHttpRequest lets you make a call back to the server from JavaScript without refreshing the whole page. A simple way of using this is to have the server return JavaScript code which is then passed to eval(). Here is a simple function for doing exactly that \u2013 it takes the URL to some JavaScript code (or a server-side script that produces JavaScript) and loads and executes that code using XMLHttpRequest and eval().\n\nfunction evalRequest(url) {\n var xmlhttp = new XMLHttpRequest();\n xmlhttp.onreadystatechange = function() {\n if (xmlhttp.readyState==4 && xmlhttp.status==200) {\n eval(xmlhttp.responseText);\n }\n }\n xmlhttp.open(\"GET\", url, true);\n xmlhttp.send(null);\n }\n\nIf you want this to work with Internet Explorer you\u2019ll need to include this compatibility patch.", "year": "2005", "author": "Simon Willison", "author_slug": "simonwillison", "published": "2005-12-07T00:00:00+00:00", "url": "https://24ways.org/2005/dont-be-eval/", "topic": "code"} {"rowid": 314, "title": "Easy Ajax with Prototype", "contents": "There\u2019s little more impressive on the web today than a appropriate touch of Ajax. Used well, Ajax brings a web interface much closer to the experience of a desktop app, and can turn a bear of an task into a pleasurable activity.\n\nBut it\u2019s really hard, right? It involves all the nasty JavaScript that no one ever does often enough to get really good at, and the browser support is patchy, and urgh it\u2019s just so much damn effort. Well, the good news is that \u2013 ta-da \u2013 it doesn\u2019t have to be a headache. But man does it still look impressive. Here\u2019s how to amaze your friends.\n\nIntroducing prototype.js\n\nPrototype is a JavaScript framework by Sam Stephenson designed to help make developing dynamic web apps a whole lot easier. In basic terms, it\u2019s a JavaScript file which you link into your page that then enables you to do cool stuff.\n\nThere\u2019s loads of capability built in, a portion of which covers our beloved Ajax. The whole thing is freely distributable under an MIT-style license, so it\u2019s good to go. What a nice man that Mr Stephenson is \u2013 friends, let us raise a hearty cup of mulled wine to his good name. Cheers! sluurrrrp.\n\nFirst step is to download the latest Prototype and put it somewhere safe. I suggest underneath the Christmas tree.\n\nCutting to the chase\n\nBefore I go on and set up an example of how to use this, let\u2019s just get to the crux. Here\u2019s how Prototype enables you to make a simple Ajax call and dump the results back to the page:\n\nvar url = 'myscript.php';\nvar pars = 'foo=bar';\nvar target = 'output-div';\t\nvar myAjax = new Ajax.Updater(target, url, {method: 'get', parameters: pars});\n\nThis snippet of JavaScript does a GET to myscript.php, with the parameter foo=bar, and when a result is returned, it places it inside the element with the ID output-div on your page.\n\nKnocking up a basic example\n\nSo to get this show on the road, there are three files we need to set up in our site alongside prototype.js. Obviously we need a basic HTML page with prototype.js linked in. This is the page the user interacts with. Secondly, we need our own JavaScript file for the glue between the interface and the stuff Prototype is doing. Lastly, we need the page (a PHP script in my case) that the Ajax is going to make its call too.\n\nSo, to that basic HTML page for the user to interact with. Here\u2019s one I found whilst out carol singing:\n\n\n\n\n \n Easy Ajax \n \n \n \n\n \n\n\n\nAs you can see, I\u2019ve linked in prototype.js, and also a file called ajax.js, which is where we\u2019ll be putting our glue. (Careful where you leave your glue, kids.)\n\nOur basic example is just going to take a name and then echo it back in the form of a seasonal greeting. There\u2019s a form with an input field for a name, and crucially a DIV (greeting) for the result of our call. You\u2019ll also notice that the form has a submit button \u2013 this is so that it can function as a regular form when no JavaScript is available. It\u2019s important not to get carried away and forget the basics of accessibility.\n\nMeanwhile, back at the server\n\nSo we need a script at the server which is going to take input from the Ajax call and return some output. This is normally where you\u2019d hook into a database and do whatever transaction you need to before returning a result. To keep this as simple as possible, all this example here will do is take the name the user has given and add it to a greeting message. Not exactly Web 2-point-HoHoHo, but there you have it.\n\nHere\u2019s a quick PHP script \u2013 greeting.php \u2013 that Santa brought me early.\n\nSeason's Greetings, $the_name!\";\n?>\n\nYou\u2019ll perhaps want to do something a little more complex within your own projects. Just sayin\u2019.\n\nGluing it all together\n\nInside our ajax.js file, we need to hook this all together. We\u2019re going to take advantage of some of the handy listener routines and such that Prototype also makes available. The first task is to attach a listener to set the scene once the window has loaded. He\u2019s how we attach an onload event to the window object and get it to call a function named init():\n\nEvent.observe(window, 'load', init, false);\n\nNow we create our init() function to do our evil bidding. Its first job of the day is to hide the submit button for those with JavaScript enabled. After that, it attaches a listener to watch for the user typing in the name field.\n\nfunction init(){\n $('greeting-submit').style.display = 'none';\n Event.observe('greeting-name', 'keyup', greet, false);\n}\n\nAs you can see, this is going to make a call to a function called greet() onkeyup in the greeting-name field. That function looks like this:\n\nfunction greet(){\n var url = 'greeting.php';\n var pars = 'greeting-name='+escape($F('greeting-name'));\n var target = 'greeting';\n var myAjax = new Ajax.Updater(target, url, {method: 'get', parameters: pars});\n}\n\nThe key points to note here are that any user input needs to be escaped before putting into the parameters so that it\u2019s URL-ready. The target is the ID of the element on the page (a DIV in our case) which will be the recipient of the output from the Ajax call.\n\nThat\u2019s it\n\nNo, seriously. That\u2019s everything. Try the example. Amaze your friends with your 1337 Ajax sk1llz.", "year": "2005", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2005-12-01T00:00:00+00:00", "url": "https://24ways.org/2005/easy-ajax-with-prototype/", "topic": "code"} {"rowid": 315, "title": "Edit-in-Place with Ajax", "contents": "Back on day one we looked at using the Prototype library to take all the hard work out of making a simple Ajax call. While that was fun and all, it didn\u2019t go that far towards implementing something really practical. We dipped our toes in, but haven\u2019t learned to swim yet.\n\nSo here is swimming lesson number one. Anyone who\u2019s used Flickr to publish their photos will be familiar with the edit-in-place system used for quickly amending titles and descriptions on photographs. Hovering over an item turns its background yellow to indicate it is editable. A simple click loads the text into an edit box, right there on the page.\n\n\n\nPrototype includes all sorts of useful methods to help reproduce something like this for our own projects. As well as the simple Ajax GETs we learned how to do last time, we can also do POSTs (which we\u2019ll need here) and a whole bunch of manipulations to the user interface \u2013 all through simple library calls. Here\u2019s what we\u2019re building, so let\u2019s do it.\n\nGetting Started\n\nThere are two major components to this process; the user interface manipulation and the Ajax call itself. Our set-up is much the same as last time (you may wish to read the first article if you\u2019ve not already done so). We have a basic HTML page which links in the prototype.js file and our own editinplace.js. Here\u2019s what Santa dropped down my chimney: \n\n\n \n \n \nEdit-in-Place with Ajax \n \n \n \n \n\nEdit-in-place
\nDashing through the snow on a one horse open sleigh.
\n \n \n\nSo that\u2019s our page. The editable item is going to be thecalled desc. The process goes something like this:\n\n\n\tHighlight the area onMouseOver\n\tClear the highlight onMouseOut\n\tIf the user clicks, hide the area and replace with a