{"database": "24ways", "table": "articles", "is_view": false, "human_description_en": "where author = \"Brian Suda\", author_slug = \"briansuda\" and topic = \"code\"", "rows": [[89, "Direction, Distance and Destinations", "With all these new smartphones in the hands of lost and confused owners, we need a better way to represent distances and directions to destinations. The immediate examples that jump to mind are augmented reality apps which let you see another world through your phone\u2019s camera. While this is interesting, there is a simpler way: letting people know how far away they are and if they are getting warmer or colder. \n\nIn the app world, you can easily tap into the phone\u2019s array of sensors such as the GPS and compass, but what people rarely know is that you can do the same with HTML. The native versus web app debate will never subside, but at least we can show you how to replicate some of the functionality progressively in HTML and JavaScript.\n\nIn this tutorial, we\u2019ll walk through how to create a simple webpage listing distances and directions of a few popular locations around the world. We\u2019ll use JavaScript to access the device\u2019s geolocation API and also attempt to access the compass to get a heading. Both of these APIs are documented, to be included in the W3C geolocation API specification, and can be used on both desktop and mobile devices today.\n\nTo get started, we need a list of a few locations around the world. I have chosen the highest mountain peak on each continent so you can see a diverse set of distances and directions. \n\n\n\t\t\n\t\t\tMountain \n\t\t\t\u00b0Latitude \n\t\t\t\u00b0Longitude \n\t\t\n\t\t\n\t\t\tKilimanjaro\n\t\t\t-3.075833\n\t\t\t37.353333\n\t\t\n\t\t\n\t\t\tVinson Massif\n\t\t\t-78.525483\n\t\t\t-85.617147\n\t\t\n\t\t\n\t\t\tPuncak Jaya\n\t\t\t-4.078889\n\t\t\t137.158333\n\t\t\n\t\t\n\t\t\tEverest\n\t\t\t27.988056\n\t\t\t86.925278\n\t\t\n\t\t\n\t\t\tElbrus\n\t\t\t43.355\n\t\t\t42.439167\n\t\t\n\t\t\n\t\t\tMount McKinley\n\t\t\t63.0695\n\t\t\t-151.0074\n\t\t\n\t\t\n\t\t\tAconcagua\n\t\t\t-32.653431\n\t\t\t-70.011083\n\t\t\n\n\nSource: Wikipedia \n\nWe can put those into an HTML list to be styled and accessed by JavaScript to create some distance and directions calculations.\n\nThe next thing we need to do is check to see if the browser and operating system have geolocation support. To do this we test to see if the function is available or not using a single JavaScript if statement.\n\n<script>\n// If this is true, then the method is supported and we can try to access the location\nif (navigator.geolocation) {\n\tnavigator.geolocation.getCurrentPosition(geo_success, geo_error);\n}\n</script>\n\nThe if statement will be false if geolocation support is not present, and then it is up to you to do something else instead as a fallback. For this example, we\u2019ll do nothing since our page should work as is and only get progressively better if more functionality is available. \n\nThe if statement will be true if there is support and therefore will continue inside the curly brackets to try to get the location. This should prompt the reader to accept or deny the request to get their location. If they say no, the second function callback is processed, in this case a function called geo_error; whereas if the location is available, it fires the geo_success function callback.\n\nThe function geo_error(){ } isn\u2019t that exciting. You can handle this in any way you see fit. The success function is more interesting. We get a position object passed into the function which contains a series of exciting attributes, namely the latitude and longitude of the device\u2019s current location.\n\nfunction geo_success(position){\n\tgLat = position.coords.latitude;\n\tgLon = position.coords.longitude;\n}\n\nNow, in the variables gLat and gLon we have the user\u2019s approximate geographical position. We can use this information to start to calculate some distances between where they are and all the destinations.\n\nAt the time of writing, you can also get position.coords.heading, but on Windows and iOS devices this returned NULL. In the future, if and when this is supported, this is also where you can easily grab the compass information.\n\nInside the geo_success function, we want to loop through the HTML to get all of the mountain peaks\u2019 latitudes and longitudes and compute the distance.\n\n...\n$('.geo').each(function(){\n\t// Get the lat/lon from the HTML\n\ttLat = $(this).find('.lat').html()\n\ttLon = $(this).find('.lon').html()\n\n\t// compute the distances between the current location and this points location\n\tdist = distance(tLat,tLon,gLat,gLon);\n\n\t// set the return values into something useful\n\td = parseInt(dist[0]*10)/10;\n\ta = parseFloat(dist[1]);\n\n\t// display the value in the HTML and style the arrow\n\t$(this).find('.distance').html(d+' km away');\n\t$(this).find('.direction').css('-webkit-transform','rotate(-' + a + 'deg)');\n\n\t// store the arc for later use if compass is available\n\t$(this).attr('data-arc',a);\n}\n\nIn the variable d we have the distance between the current location and the location of the mountain peak based on the Haversine Formula. The variable a is the arc, which has a value from 0 to 359.99. This will be useful later if we have compass support. Given these two values we have a distance and a heading to style the HTML.\n\nThe next thing we want to do is check to see if the device has a compass and then get access to the the current heading. As we\u2019ll see, there are several ways to do this, some of which work on certain devices but not others. The W3C geolocation spec says that, along with the coordinates, there are several other attributes: accuracy; altitude; and heading. Heading is the direction to true north, which is different than magnetic north! WebKit and Windows return NULL for the heading value, but WebKit has an experimental method to fetch the heading. If you get into accessing these sensors, you\u2019ll have to try to catch a few of these methods to finally get a value. Assuming you do, we can move on to the more interesting display opportunities.\n\nIn an ideal world, this would succeed and set a variable we\u2019ll call compassHeading to get a value between 0 and 359.99 degrees. Now we know which direction north is, we also know the direction relative to north of the path to our destination, so we can can subtract the two values to get an arrow to display on the screen. But we\u2019re not finished yet: we also need to get the device\u2019s orientation (landscape or portrait) and subtract the correct amount from the angle for the arrow. Once we have a value, we can use CSS to rotate the arrow the correct number of degrees.\n\n-webkit-transform: rotate(-180deg)\n\nNot all devices support a standard way to access compass information, so in the meantime we need to use a work around. On iOS, you can use the experimental event method e.webkitCompassHeading. We want the compass to update in real time as the device is moved around, so we\u2019ll put this inside an event listener.\n\nwindow.addEventListener('deviceorientation', function(e) {\n\t// Loop through all the locations on the page\n\t$('.geo').each(function(){\n\t\t// get the arc value from north we computed and stored earlier\n\t\tdestination_arc = parseInt($(this).attr('data-arc'))\n\t\tcompassHeading = e.webkitCompassHeading + window.orientation + destination_arc;\n\t\t// find the arrow element and rotate it accordingly\n\t\t$(this).find('.direction').css('-webkit-transform','rotate(-' + compassHeading + 'deg)');\t\t\n\t}\n}\n\nAs the device is rotated, the compass arrow will constantly be updated. If you want to see an example, you can have a look at this page which shows the distances to all the peaks on each continent.\n\nWith progressive enhancement, we slowly layer on additional functionality as we go. The reader will first see the list of locations with a latitude and longitude. If the device is capable and permissions allow, it will then compute the distance. If a compass is available, with the correct permissions it will then add the final layer which is direction.\n\nYou should consider this code a stub for your projects. If you are making a hyperlocal webpage with restaurant locations, for example, then consider adding these features. Knowing not only how far away a place is, but also the direction can be hugely important, and since the compass is always active, it acts as a guide to the location. \n\nFuture developments\n\nImprovements to this could include setting a timer and recalling the navigator.geolocation.getCurrentPosition() function and updating the distances. I chose very distant mountains so kilometres made sense, but you can divide again by 1,000 to convert to metres if you are dealing with much nearer places. Walking or driving would change the distances so the ability to refresh would be important. \n\nIt is outside the scope of this article, but if you manage to get this HTML to work offline, then you can make a nice web app which sits on your devices\u2019 homescreens and works even without an internet connection. This could be ideal for travellers in an unknown city looking for your destination. Just with offline storage, base64 encoding and data URIs, it is possible to embed plenty of design and functionality into a small offline webpage.\n\nNow you know how to use JavaScript to look up a destination\u2019s location and figure out the distance and direction \u2013 never get lost again.", "2012", "Brian Suda", "briansuda", "2012-12-19T00:00:00+00:00", "https://24ways.org/2012/direction-distance-and-destinations/", "code"], [100, "Moo'y Christmas", "A note from the editors:  Moo has changed their API since this article was written.\n                \n                \n                      \n                As the web matures, it is less and less just about the virtual world. It is becoming entangled with our world and it is harder to tell what is virtual and what is real. There are several companies who are blurring this line and make the virtual just an extension of the physical. Moo is one such company. \n\nMoo offers simple print on demand services. You can print business cards, moo mini cards, stickers, postcards and more. They give you the ability to upload your images, customize them, then have them sent to your door. Many companies allow this sort of digital to physical interaction, but Moo has taken it one step further and has built an API. \n\nPrintable stocking stuffers \n\nThe Moo API consists of a simple XML file that is sent to their servers. It describes all the information needed to dynamically assemble and print your object. This is very helpful, not just for when you want to print your own stickers, but when you want to offer them to your customers, friends, organization or community with no hassle. Moo handles the check-out and shipping, all you need to do is what you do best, create! \n\nNow using an API sounds complicated, but it is actually very easy. I am going to walk you through the options so you can easily be printing in no time. \n\nBefore you can begin sending data to the Moo API, you need to register and get an API key. This is important, because it allows Moo to track usage and to credit you. To register, visit http://www.moo.com/api/ and click \u201cRequest an API key\u201d. \n\nIn the following examples, I will use {YOUR API KEY HERE} as a place holder, replace that with your API key and everything will work fine. \n\nFirst thing you need to do is to create an XML file to describe the check-out basket. Open any text-editor and start with some XML basics. Don\u2019t worry, this is pretty simple and Moo gives you a few tools to check your XML for errors before you order. \n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n<moo xsi:noNamespaceSchemaLocation=\"http://www.moo.com/xsd/api_0.7.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n\t <request>\n\t\t <version>0.7</version>\n\t\t <api_key>{YOUR API KEY HERE}</api_key>\n\t\t <call>build</call>\n\t\t <return_to>http://www.example.com/return.html</return_to>\n\t\t <fail_to>http://www.example.com/fail.html</fail_to>\n\t </request>\n\t <payload>\n\t ...\n\t </payload>\n</moo>\n\nMuch like HTML\u2019s <head> and <body>, Moo has created <request> and <payload> elements all wrapped in a <moo> element. \n\nThe <request> element contains a few pieces of information that is the same across all the API calls. The <version> element describes which version of the API is being used. This is more important for Moo than for you, so just stick with \u201c0.7\u201d for now. \n\nThe <api_key> allows Moo to track sales, referrers and credit your account. \n\nThe <call> element can only take \u201cbuild\u201d so that is pretty straight forward. The <return_to> and <fail_to> elements are URLs. These are optional and are the URLs the customer is redirected to if there is an error, or when the check out process is complete. This allows for some basic branding and a custom \u201cthank you\u201d page which is under your control. That\u2019s it for the <request> element, pretty easy so far! \n\nNext up is the <payload> element. What goes inside here describes what is to be printed. There are two possible elements, we can put <chooser> or we can put <products> directly inside <payload>. They work in a similar ways, but they drop the customer into different parts of the Moo checkout process. \n\nIf you specify <products> then you send the customer straight to the Moo payment process. If you specify <chooser> then you send the customer one-step earlier where they are allowed to pick and choose some images, remove the ones they don\u2019t like, adjust the crop, etc. The example here will use <chooser> but with a little bit of homework you can easily adjust to <products> if you desire. \n\n... \n<chooser> \n\t <product_type>sticker</product_type> \n\t <images> \n\t\t <url>http://example.com/images/christmas1.jpg</url> \n\t </images> \n</chooser> \n...\n\nInside the <chooser> element, we can see there are two basic piece of information. The type of product we want to print, and the images that are to be printed. The <product_type> element can take one of five options and is required! The possibilities are: minicard, notecard, sticker, postcard or greetingcard. We\u2019ll now look at two of these more closely. \n\nMoo Stickers \n\nIn the Moo sticker books you get 90 small squarish stickers in a small little booklet. \n\n\n\nThe simplest XML you could send would be something like the following payload:\n\n...\n<payload>\n\t<chooser>\n\t\t<product_type>sticker</product_type>\n\t\t<images>\n\t\t\t<url>http://example.com/image1.jpg</url>\n\t\t</images>\n\t\t<images>\n\t\t\t<url>http://example.com/image2.jpg</url>\n\t\t</images>\n\t\t<images>\n\t\t\t<url>http://example.com/image3.jpg</url>\n\t\t</images>\n\t</chooser>\n</payload>\n...\n\nThis creates a sticker book with only 3 unique images, but 30 copies of each image. The Sticker books always print 90 stickers in multiples of the images you uploaded. That example only has 3 <images> elements, but you can easily duplicate the XML and send up to 90. The <url> should be the full path to your image and the image needs to be a minimum of 300 pixels by 300 pixels.\n\nYou can add more XML to describe cropping, but the simplest option is to either, let your customers choose or to pre-crop all your images square so there are no issues.\n\nThe full XML you would post to the Moo API to print sticker books would look like this:\n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n<moo xsi:noNamespaceSchemaLocation=\"http://www.moo.com/xsd/api_0.7.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n\t<request>\n\t\t<version>0.7</version>\n\t\t<api_key>{YOUR API KEY HERE}</api_key>\n\t\t<call>build</call>\n\t\t<return_to>http://www.example.com/return.html</return_to>\n\t\t<fail_to>http://www.example.com/fail.html</fail_to>\n\t</request>\n\t<payload>\n\t\t<chooser>\n\t\t\t<product_type>sticker</product_type>\n\t\t\t<images>\n\t\t\t\t<url>http://example.com/image1.jpg</url>\n\t\t\t</images>\n\t\t\t<images>\n\t\t\t\t<url>http://example.com/image2.jpg</url>\n\t\t\t</images>\n\t\t\t<images>\n\t\t\t\t<url>http://example.com/image3.jpg</url>\n\t\t\t</images>\n\t\t</chooser>\n\t</payload> \n</moo>\n\nMini-cards \n\nThe mini-cards are the small cute business cards in 14\u00d735 dimensions and come in packs of 100. \n\n\n\nSince the mini-cards are print on demand, this allows you to have 100 unique images on the back of the cards.\n\nJust like the stickers example, we need the same XML setup. The <moo> element and <request> elements will be the same as before. The part you will focus on is the <payload> section. \n\nSince you are sending along specific information, we can\u2019t use the <chooser> option any more. Switch this to <products> which has a child of <product>, which in turn has a <product_type> and <designs>. This might seem like a lot of work, but once you have it set up you won\u2019t need to change it.\n\n...\n<payload>\n\t<products>\n\t\t<product>\n\t\t\t<product_type>minicard</product_type>\n\t\t\t<designs>\n\t\t\t\t...\n\t\t\t</designs>\n\t\t</product>\n\t</products>\n</payload>\n...\n\nSo now that we have the basic framework, we can talk about the information specific to minicards. Inside the <designs> element, you will have one <design> for each card. Much like before, this contains a way to describe the image. Note that this time the element is called <image>, not images plural. \n\nInside the <image> element you have a <url> which points to where the image lives and a <type>. The <type> should just be set to \u2018variable\u2019. You can pass crop information here instead, but we\u2019re going to keep it simple for this tutorial. If you are interested in how that works, you should refer to the official API documentation.\n\n...\n<design>\n\t<image>\n\t\t<url>http://example.com/image1.jpg</url>\n\t\t<type>variable</type>\n\t</image>\n</design>\n...\n\nSo far, we have managed to build a pack of 100 Moo mini-cards with the same image on the front. If you wanted 100 different images, you just need to replicate this snippit, 99 more times.\n\nThat describes the front design, but the flip-side of your mini-cards can contain 6 lines of text, which is customizable in a variety of colors, fonts and styles.\n\nThe API allows you to create different text on the back of each mini-card, something the web interface doesn\u2019t implement. To describe the text on the mini-card we need to add a <text_collection> element inside the <design> element. If you skip this element, the back of your mini-card will just be blank, but that\u2019s not very festive!\n\nInside the <text_collection> element, we need to describe the type of text we want to format, so we add a <minicard> element, which in turn contains all the lines of text. Each of Moo\u2019s printed products take different numbers of lines of text, so if you are not planning on making mini-cards, be sure to consult the documentation.\n\nFor mini-cards, we can have 6 distinct lines, each with their own style and layout. Each line is represented by an element <text_line> which has several optional children. The <id> tells which line of the 6 to print the text one. The <string> is the text you want to print and it must be shorter than 38 characters. The <bold> element is false by default, but if you want your text bolded, then add this and set it to true. \n\nThe <align> element is also optional. By default it is set to align left. You can also set this to right or center if you desirer. The <font> element takes one of 3 types, modern, traditional or typewriter. The default is modern. Finally, you can set the <colour>, yes that\u2019s color with a \u2018u\u2019, Moo is a British company, so they get to make the rules. When you start a print on demand company, you can spell it however you want. The <colour> element takes a 6 character hex value with a leading #.\n\n<design>\n\t...\n\t<text_collection>\n\t\t<minicard>\n\t\t\t<text_line>\n\t\t\t\t<id>(1-6)</id>\n\t\t\t\t<string>String, I must be less than 38 chars!</string>\n\t\t\t\t<bold>true</bold>\n\t\t\t\t<align>left</align>\n\t\t\t\t<font>modern</font>\n\t\t\t\t<colour>#ff0000</colour> \n\t\t\t</text_line>\n\t\t</minicard>\n\t</text_collection>\n</design>\n\nIf you combine all of this into a mini-card request you\u2019d get this example:\n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n<moo xsi:noNamespaceSchemaLocation=\"http://www.moo.com/xsd/api_0.7.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n\t<request>\n\t\t<version>0.7</version>\n\t\t<api_key>{YOUR API KEY HERE}</api_key>\n\t\t<call>build</call>\n\t\t<return_to>http://www.example.com/return.html</return_to>\n\t\t<fail_to>http://www.example.com/fail.html</fail_to>\n\t</request>\n\t<payload>\n\t\t<products>\n\t\t\t<product>\n\t\t\t\t<product_type>minicard</product_type>\n\t\t\t\t<designs>\n\t\t\t\t\t<design>\n\t\t\t\t\t\t<image>\n\t\t\t\t\t\t\t<url>http://example.com/image1.jpg</url>\n\t\t\t\t\t\t\t<type>variable</type>\n\t\t\t\t\t\t</image>\n\t\t\t\t\t\t<text_collection>\n\t\t\t\t\t\t\t<minicard>\n\t\t\t\t\t\t\t\t<text_line>\n\t\t\t\t\t\t\t\t<id>1</id>\n\t\t\t\t\t\t\t\t<string>String, I must be less than 38 chars!</string>\n\t\t\t\t\t\t\t\t<bold>true</bold>\n\t\t\t\t\t\t\t\t<align>left</align>\n\t\t\t\t\t\t\t\t<font>modern</font>\n\t\t\t\t\t\t\t\t<colour>#ff0000</colour> \n\t\t\t\t\t\t\t\t</text_line>\n\t\t\t\t\t\t\t</minicard>\n\t\t\t\t\t\t</text_collection>\n\t\t\t\t\t</design>\n\t\t\t\t</designs>\n\t\t\t</product>\n\t\t</products>\n\t</payload> \n</moo>\n\nNow you know how to construct the XML that describes what to print. Next, you need to know how to send it to Moo to make it happen!\n\nPosting to the API\n\nSo your XML is file ready to go. First thing we need to do is check it to make sure it\u2019s valid. Moo has created a simple validator where you paste in your XML, and it alerts you to problems.\n\nWhen you have a fully valid XML file, you\u2019ll want to send that to the Moo API. There are a few ways to do this, but the simplest is with an HTML form. \n\nThis is the sample code for an HTML form with a big \u201cBuy My Stickers\u201d button. Once you know that it is working, you can use all your existing HTML knowledge to style it up any way you like.\n\n<form method=\"POST\" action=\"http://www.moo.com/api/api.php\">\n\t<input type=\"hidden\" name=\"xml\" value=\"<?xml version=\"1.0\" encoding=\"UTF-8\"?> <moo xsi:noNamespaceSchemaLocation=\"http://www.moo.com/xsd/api_0.7.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <request>....</request> <payload>...</payload> </moo> \"> \n\t<input type=\"submit\" name=\"submit\" value=\"Buy My Stickers\"/>\n</form>\n\nThis is just a basic <form> element that submits to the Moo API, http://www.moo.com/api/api.php, when someone clicks the button. There is a hidden input called \u201cxml\u201d which contains the value the XML file we created previously.\n\nFor those of you who need to \u201cview source\u201d to fully understand what\u2019s happening can see a working version and peek under the hood.\n\nUsing the API has advantages over uploading the images directly yourself. The images and text that you send via the API can be dynamic. Some companies, like Dopplr, have taken user profiles and dynamic data that changes every minute to generate customer stickers of places that you\u2019ve travelled to or mini-cards with a world map of all the cities you have visited. Every single customer has different travel plans and therefore different sets of stickers and mini-card maps. The API allows for the utmost current information to be printed, on demand, in real-time.\n\nGo forth and Moo\u2019ltiply\n\nSee, making an API call wasn\u2019t that hard was it? You are now 90% of the way to creating anything with the Moo API. With a bit of reading, you can learn that extra 10% and print any Moo product. Be on the lookout in 2009 for the official release of the 1.0 API with improvements and some extras that were not available when this article was written.\n\nThis article is released under the creative-commons attribution share-a-like license. That means you are free to re-distribute it, mash it up, translate it and otherwise re-using it ways the author never considered, in return he only asks you mention his name.\n\n\nThis work by Brian Suda is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.", "2008", "Brian Suda", "briansuda", "2008-12-19T00:00:00+00:00", "https://24ways.org/2008/mooy-christmas/", "code"], [223, "Calculating Color Contrast", "Some websites and services allow you to customize your profile by uploading pictures, changing the background color or other aspects of the design. As a customer, this personalization turns a web app into your little nest where you store your data. As a designer, letting your customers have free rein over the layout and design is a scary prospect. So what happens to all the stock text and images that are designed to work on nice white backgrounds? Even the Mac only lets you choose between two colors for the OS, blue or graphite! Opening up the ability to customize your site\u2019s color scheme can be a recipe for disaster unless you are flexible and understand how to find maximum color contrasts.\n\nIn this article I will walk you through two simple equations to determine if you should be using white or black text depending on the color of the background. The equations are both easy to implement and produce similar results. It isn\u2019t a matter of which is better, but more the fact that you are using one at all! That way, even with the craziest of Geocities color schemes that your customers choose, at least your text will still be readable.\n\nLet\u2019s have a look at a range of various possible colors. Maybe these are pre-made color schemes, corporate colors, or plucked from an image.\n\n\n\nNow that we have these potential background colors and their hex values, we need to find out whether the corresponding text should be in white or black, based on which has a higher contrast, therefore affording the best readability. This can be done at runtime with JavaScript or in the back-end before the HTML is served up.\n\nThere are two functions I want to compare. The first, I call \u201950%\u2019. It takes the hex value and compares it to the value halfway between pure black and pure white. If the hex value is less than half, meaning it is on the darker side of the spectrum, it returns white as the text color. If the result is greater than half, it\u2019s on the lighter side of the spectrum and returns black as the text value.\n\nIn PHP:\n\nfunction getContrast50($hexcolor){\n    return (hexdec($hexcolor) > 0xffffff/2) ? 'black':'white';\n}\n\nIn JavaScript:\n\nfunction getContrast50(hexcolor){\n    return (parseInt(hexcolor, 16) > 0xffffff/2) ? 'black':'white';\n}\n\nIt doesn\u2019t get much simpler than that! The function converts the six-character hex color into an integer and compares that to one half the integer value of pure white. The function is easy to remember, but is naive when it comes to understanding how we perceive parts of the spectrum. Different wavelengths have greater or lesser impact on the contrast.\n\nThe second equation is called \u2018YIQ\u2019 because it converts the RGB color space into YIQ, which takes into account the different impacts of its constituent parts. Again, the equation returns white or black and it\u2019s also very easy to implement.\n\nIn PHP:\n\nfunction getContrastYIQ($hexcolor){\n\t$r = hexdec(substr($hexcolor,0,2));\n\t$g = hexdec(substr($hexcolor,2,2));\n\t$b = hexdec(substr($hexcolor,4,2));\n\t$yiq = (($r*299)+($g*587)+($b*114))/1000;\n\treturn ($yiq >= 128) ? 'black' : 'white';\n}\n\nIn JavaScript:\n\nfunction getContrastYIQ(hexcolor){\n\tvar r = parseInt(hexcolor.substr(0,2),16);\n\tvar g = parseInt(hexcolor.substr(2,2),16);\n\tvar b = parseInt(hexcolor.substr(4,2),16);\n\tvar yiq = ((r*299)+(g*587)+(b*114))/1000;\n\treturn (yiq >= 128) ? 'black' : 'white';\n}\n\nYou\u2019ll notice first that we have broken down the hex value into separate RGB values. This is important because each of these channels is scaled in accordance to its visual impact. Once everything is scaled and normalized, it will be in a range between zero and 255. Much like the previous \u201950%\u2019 function, we now need to check if the input is above or below halfway. Depending on where that value is, we\u2019ll return the corresponding highest contrasting color.\n\nThat\u2019s it: two simple contrast equations which work really well to determine the best readability.\n\nIf you are interested in learning more, the W3C has a few documents about color contrast and how to determine if there is enough contrast between any two colors. This is important for accessibility to make sure there is enough contrast between your text and link colors and the background.\n\nThere is also a great article by Kevin Hale on Particletree about his experience with choosing light or dark themes. To round it out, Jonathan Snook created a color contrast picker which allows you to play with RGB sliders to get values for YIQ, contrast and others. That way you can quickly fiddle with the knobs to find the right balance.\n\nComparing results\n\nLet\u2019s revisit our color schemes and see which text color is recommended for maximum contrast based on these two equations.\n\n\n\nIf we use the simple \u201950%\u2019 contrast function, we can see that it recommends black against all the colors except the dark green and purple on the second row. In general, the equation feels the colors are light and that black is a better choice for the text.\n\n\n\nThe more complex \u2018YIQ\u2019 function, with its weighted colors, has slightly different suggestions. White text is still recommended for the very dark colors, but there are some surprises. The red and pink values show white text rather than black. This equation takes into account the weight of the red value and determines that the hue is dark enough for white text to show the most contrast.\n\nAs you can see, the two contrast algorithms agree most of the time. There are some instances where they conflict, but overall you can use the equation that you prefer. I don\u2019t think it is a major issue if some edge-case colors get one contrast over another, they are still very readable.\n\nNow let\u2019s look at some common colors and then see how the two functions compare. You can quickly see that they do pretty well across the whole spectrum.\n\n\n\nIn the first few shades of grey, the white and black contrasts make sense, but as we test other colors in the spectrum, we do get some unexpected deviation. Pure red #FF0000 has a flip-flop. This is due to how the \u2018YIQ\u2019 function weights the RGB parts. While you might have a personal preference for one style over another, both are justifiable.\n\n\n\nIn this second round of colors, we go deeper into the spectrum, off the beaten track. Again, most of the time the contrasting algorithms are in sync, but every once in a while they disagree. You can select which you prefer, neither of which is unreadable.\n\nConclusion\n\nContrast in color is important, especially if you cede all control and take a hands-off approach to the design. It is important to select smart defaults by making the contrast between colors as high as possible. This makes it easier for your customers to read, increases accessibility and is generally just easier on the eyes. \n\nSure, there are plenty of other equations out there to determine contrast; what is most important is that you pick one and implement it into your system.\n\nSo, go ahead and experiment with color in your design. You now know how easy it is to guarantee that your text will be the most readable in any circumstance.", "2010", "Brian Suda", "briansuda", "2010-12-24T00:00:00+00:00", "https://24ways.org/2010/calculating-color-contrast/", "code"]], "truncated": false, "table_rows_count": 336, "filtered_table_rows_count": 3, "expanded_columns": [], "expandable_columns": [], "columns": ["rowid", "title", "contents", "year", "author", "author_slug", "published", "url", "topic"], "primary_keys": [], "units": {}, "query": {"sql": "select rowid, * from articles where \"author\" = :p0 and \"author_slug\" = :p1 and \"topic\" = :p2 order by rowid limit 101", "params": {"p0": "Brian Suda", "p1": "briansuda", "p2": "code"}}, "facet_results": {}, "suggested_facets": [], "next": null, "next_url": null, "query_ms": 11.73543930053711}