Montag, 30. Juni 2014

The `time` Element




CSS-Tricks





The `time` Element



The following is a guest post by Ty Strong. Ty noticed a curious lack of information on the <time> element here on CSS-Tricks and I agreed. Can't let that happen! Take it away Ty.



The <time> element in HTML represents a machine-readable date, time, or duration. It can be useful for creating event scheduling, archiving, and other time-based functions. WordPress uses the time element in the default theme. Reddit uses the time element as well.




Reddit using the <time> element for posting dates.



A Brief History


The time element has had a rocky road. It was added to the HTML5 specs back in 2009. Two years later in 2011, the spec was dropped and replaced with a much broader element, <data>. Later that year the time element was added back with some revamped features.


Rest assured, you can use it!


Bruce Lawson covers the situation well: gone, back, now. A classic "paving the cowpaths" moment in HTML history.


The Tag and Attribute


Time is just an HTML tag. Here's a simple example that represents November 2011:


<time>2011-11</time>

The text in there happens to be a valid datetime attribute value (more on that in a moment). But it doesn't have to be. You could move that text into a datetime attribute and use different text.


<time datetime="2011-11">A cold winter month many years ago</time>

The datetime attribute is what makes the time element unique. It represents the date, time, or duration for whatever text you are representing in a machine readable format. That means it is for computers, not humans, so it has very specific formats.


It's probably a bit more common for the human-readable version to be just a textual representation of the datetime:


<time datetime="2011-11">November, 2011</time>

10 Ways


There are a variety of standard ways to format the datetime attribute.


Year and Month


2014-06

Very Simple. Year before month.


Date


1969-07-16

Year, month, and then day.


Yearless Date


12-31

Month before day.


Time Only


14:54:39.929

Hour, minute, then seconds. Seconds is optional. Fractions of a second can be represented up to three digits.


Date and Time


2013-11-20T14:54

Combination of Date and Time, separated by a capital T. The capital "T" can be replaced with a space.


Time-Zone Offset


+06:00

Starts with plus or minus sign. Colon (:) is optional. +00:00, or UTC time, can be represented by the capital letter "Z".


Local Date and Time


2019-12-31T23:59:59-02:00

This is the same as Date and Time with an added time-zone offset. Again, "T" can be replaced with a space.


Year and Week


2010-W21

Year followed by a capital "W" with the corresponding number week.


Year Only


1776

This must be four digits or more, so `0001` and `12345` both work.


Duration (Method One)


P2DT2H30M10.501S

Capital "P", an optional day value, capital "T", then optional values of hours, minutes, and seconds. All letters must be upper-case.


Duration (Method Two)


1w 2d 2h 30m 10.501s

Week (w), Day (d), Hour (h), Minute (m), and Seconds (s). Letter can be upper-case or lower-case. Spaces are optional.


Examples


Google released Gmail Blue on <time datetime="2013-04-01">April 1st, 2013</time>.

The Chelyabinsk meteor entered Earth's atmosphere over Russia on <time datetime="2013-02-15T09:20+06:00">15 February 2013 at about 09:20 YEKT (03:20 UTC)</time>.

The Apollo 13 mission lasted a total of <time datetime="5d 22h 54m 41s">5 days, 22 hours, 54 minutes, and 41 seconds</time>.

Having Trouble Formatting the Datetime?


Using this little tool you can input a certain date or time (or both), and it will output the correct datetime value.


See the Pen Datetime Creator Tool by Chris Coyier (@chriscoyier) on CodePen.


Browser Support


Browser support isn't a major concern with the time element. If a browser is familiar with it, great, if not, it will treat it as a generic inline element which is perfectly fine. The datetime attribute is also perfectly accessible.


There is a DOM interface associated with the time element though. Specifically dateTime should be available on a reference to that element.


<p>The concert took place on <time datetime="2001-05-15 19:00">May 15</time>.</p>
<script>
var time = document.getElementsByTagName("time")[0];
console.log(time.dateTime);
// outputs "2001-05-15 19:00"
</script>

This is only supported in Firefox, and isn't particularly useful anyway since all it does is return that attribute (it doesn't even return a value value if the attribute isn't there but the text is a valid value, which seems like it would make sense.)


What is the benefit to using <time>?


I'm going to quote Bruce again because he says it very well in a post on HTML5 Doctor:


The uses of unambiguous dates in web pages aren’t hard to imagine. A browser could offer to add events to a user’s calendar. A Thai-localised browser could offer to transform Gregorian dates into Thai Buddhist era dates. A Japanese browser could localise <time>16:00</time> to "16:00時". Content aggregators can produce visual timelines of events.


Search engines can produce smarter search results. For example, in the recent heavy snow in the UK, I searched for school closures in my town and discovered my kids’ school was closed. After receiving a phone call from the school asking me where my kids were, I re-examined the webpage. In small print at the bottom of the page were the words "Published 5 January 2008". I expect that operators of search engines would rank more current pages more highly on searches connected with current events.


Other Bits


A further touch you can do to the time element is adding a title attribute to expose more detailed information to the user. Meaning you can offer the same bit of information three ways:



  • A nice human-readable display format

  • A more detailed human-readable hover format

  • A machine-readable format


This is in use on CodePen:



This is the Rails code that outputs those different formats (STRFTIME is a nice tool for that):


<time 
datetime="<%= @pen.created_at.strftime("%Y-%m-%dT%H:%M") %>"
title="<%= @pen.created_at.strftime("%Y-%m-%d at %I:%M %p") %>">
<%= @pen.created_at.strftime("%B %d, %Y") %>
</time>

Are you using <time> on any of your projects?




The `time` Element is a post from CSS-Tricks








Mittwoch, 25. Juni 2014

Sponsor: Colore Maps




CSS-Tricks





Sponsor: Colore Maps



Make data visualization maps directly in your browser for free! Use the visual map editor to create geographic infographics for your website or for use in presentations. Your maps will work everywhere, including mobile devices, with no limitations on use. Only pay for advanced features like auto-updating maps or for a professional consultation.


Direct Link to ArticlePermalink



Sponsor: Colore Maps is a post from CSS-Tricks








Dienstag, 24. Juni 2014

Web Technologies Hanging Out Together




CSS-Tricks





Web Technologies Hanging Out Together



As a beginner, understanding how the different languages you learn interact with each other can be confusing. I thought we could pair up a variety of languages to see where they intersect and communicate.



HTML and CSS


You need HTML to have CSS, because HTML calls the CSS. In an HTML document, you'll likely see some HTML like this:


<link rel="stylesheet" href="style.css">

That is an HTML element (<link>) calling some CSS that will then be applied to the HTML. Or you might see a "style block" like this:


<!-- this <style> tag is HTML -->
<style>
/* The stuff in here is CSS */
.message {
padding: 20px;
background: lightyellow;
border: 1px solid yellow;
}
</style>

The typical connection between HTML and CSS is with selectors. An HTML element might have an ID or class, which doesn't do much by itself, but is there for CSS to find it and style it. Like:


<div class="module message">
<h2 class="positive">
Good afternoon!
<h2>
<p>
You look nice today.
</p>
</div>

.module { /* will apply to <div class="module message"> */
padding: 20px;
background: rgba(0, 0, 0, 0.2);
}
.message { /* will apply to <div class="module message"> */
border: 1px solid yellow;
}
.positive { /* will apply to <h2 class="positive"> */
color: lightblue;
font-weight: bold;
}

CSS can even be applied directly to elements in HTML. In that case there is no selector, just properties and values:


<div style="padding: 10px; background: red; color: white;">
Emergency!
</div>

Using CSS this way is generally frowned upon because it doesn't take advantage of what HTML and CSS do so wonderfully together: separate content and style.


HTML and JavaScript


You need HTML to call JavaScript. In an HTML document, you might see:


<script src="script.js"></script>

That is an HTML element (<script>) that calls a JavaScript file that will then run in that document. Or you might see a script tag with no source, an inline script block:


<!-- the <script> tag is HTML -->
<script>
// The stuff in here is JavaScript
var header = document.getElementById("main-header");
</script>

You might also see JavaScript directly on HTML elements, like this:


<button onclick="doSomething();"></button>

Using JavaScript "inline" like that is generally frowned upon, because it isn't very efficient and doesn't separate the concerns of content and interaction.


Another relationship between HTML and JavaScript is that JavaScript can control the DOM. The DOM is essentially what HTML turns into when a browser reads it. You can read more about that here.


JavaScript can create new HTML and insert it onto the page:


// Create new element
var modal = document.createElement('div');

// Set attributes and content
modal.id = "modal";
modal.innerHTML = "\
<h1>Important Message</h1>\
<p>You're cool.</p>";

// Put in the <body>
document.documentElement.appendChild(modal);

JavaScript can remove elements from the page as well:


var reference = document.getElementById("goner");
reference.parentNode.removeChild(reference);

JavaScript can alter the content of existing elements as well:


var reference = document.querySelectorAll("#modal > h1");
reference[0].innerHTML = "This title has been changed by JS!";

JavaScript and CSS


JavaScript can find out about an element's style:


<div style="color: red;" id="test">test</div>
<script>
var div = document.getElementById("test");
console.log(div.style.color);
// red

// and/or *set* it like:
div.style.padding = "10px";
</script>

But that only works for an elements inline style attribute (or styles set in that way). JavaScript can also get all the styles on an element, even those that came from CSS elsewhere:


<style>
.test {
margin: 30px;
}
<style>

<div class="test"></div>

<script>
var div = document.querySelectorAll(".test")[0];

var styles = getComputedStyle(div);

console.log(styles.margin);
// 30px
</script>

More commonly, because JavaScript is our primary means of handling interactivity on websites, we use it to control other elements. Here's a simple example of a button that, when clicked, toggles the whether you can see another element or not:


<button class="button">Toggle Another Element</button>

<div id="message">Message</div>

var button = document.querySelectorAll(".button")[0];
var message = document.querySelectorAll("#message")[0];

button.addEventListener("click", function() {
if (message.style.display == "block") {
message.style.display = "none";
} else {
message.style.display = "block";
}
});

Perhaps even more common (and generally considered to be responsible) is to only manipulate class names on elements, rather than styles directly. Then let CSS handle the styles (which includes whether it is visible or not). It ends up being easier anyway:


#message {
display: none;
}
#message.show {
display: block;
}

var button = document.querySelectorAll(".button")[0];
var message = document.querySelectorAll("#message")[0];

button.addEventListener("click", function() {
message.classList.toggle("show");
}, false);

See the Pen qidGm by Chris Coyier (@chriscoyier) on CodePen.


HTML and PHP


The HTML you work with might actually be in a back end language like PHP and is processed and delivered as HTML. Imagine a template for a blog:


<h1>
<?php echo $postTitle; ?>
</h1>
<div class="post-content">
<?php echo $postContent; ?>
</div>

In this article we're just using PHP as an example of a backend language. But it could just as easily be Ruby or Python or the like.


You'll recognize HTML there, but PHP mingled in. That is just a generic example of outputting values that a backend language might be in charge of. The web browser never sees the code like that. By the time it makes it to the browser, it will look like regular HTML:


<h1>
How To Survive A Flight Delay Without Tweeting About It
</h1>
<div class="post-content">
Step one, grow up.
</div>

As a front end person, you might think of PHP as the link between information in a database and HTML.


Another possibility would be outputting different HTML based on information you know on the server.


<?php $userLikesCheese = doesUserLikeCheese($user); ?>

<?php if ($userLikesCheese) { ?>
<div class="modal">
Congrats on loving cheese, cheese lover!
</div>
<?php } else { ?>
<div class="modal">
Some other way more boring widget.
</div>
<?php } ?>

PHP and JavaScript


Speaking of a database, you might need information that comes from the server in JavaScript.



JavaScript also has the ability to make a request to a URL all on its own. Imagine clicking a "like" button on a page. You wouldn't expect that to refresh the entire page. Instead, that action might make a request to a PHP file on your server that's job it is to save that information.


var button = document.querySelectorAll(".button")[0];

button.addEventListener("click", function() {
var xhr = new XMLHttpRequest();
xhr.onload = likeSuccess;
xhr.open("get", "/save_like.php", true);
xhr.send();
});

function likeSuccess() {
button.innerHTML = "You Like Stuff!";
}

See the Pen gomvI by Chris Coyier (@chriscoyier) on CodePen.


PHP and CSS


Just like PHP documents can be processed and served as HTML, the same can happen with CSS. This means you could do things like utilize the power of PHP variables in CSS. I've written about this before, but I'd argue today this isn't a particularly good idea. I'd recommend instead taking a look at CSS preprocessing.


Another connection is using PHP to alter class names or attributes, and then CSS acts accordingly.


<body class="<?php echo $bodyClass; ?>">

<header>
Probably a logo and stuff.
</header>

</body>

header {
height: 100px;
}

/* header is bigger on homepage */
body.home header {
height: 200px;
}

Of course it gets way more complicated.


It should go without saying, right? Sometimes it just is. But these aren't just "the basics" - they are foundational concepts that more complicated things are built from.


Perhaps you learned how to make an Ajax request with jQuery and it doesn't look like the one I did above. Well, somewhere in that jQuery library, which is written in JavaScript, it's doing that same thing. It's just got some extra stuff in there to make sure it works in older browsers and adds convenience for you.


Perhaps you're using Angular and the way you change stuff on the page is with weird {{angle brackets}} in your HTML. That's nifty, but somewhere Angular is doing something with "raw" JavaScript. An .innerHTML is being used or a node is being replaced, who knows. The people who work on Angular figured out the best way to do it and that's what it does.


Maybe the CMS you use at work has some different looking templating system. That's cool. I'll bet you a billion bucks it gets turned into HTML before it hits the browser, because that's how this all goes down.


The point: it's all related.


You can be better at some of these languages than others. All of us are. Totally fine. But it is important to understand how they fit together. That's all of our jobs.


My inspiration for this came from my own utter confusion when I'd hear someone from some startup rattle off their "tech stack" and I just didn't comprehend how all those things could possibly fit together to build one thing. I'm still confused, but it doesn't matter. I understand how the parts fit together well enough that any part I've never heard of is surely just some newfangled way to handle the same pieces of the web tech pie that we all deal with.




Web Technologies Hanging Out Together is a post from CSS-Tricks








Samstag, 21. Juni 2014

rebeccapurple = #663399




CSS-Tricks





rebeccapurple = #663399



... it is suggested to add the named color 'rebeccapurple', for value #663399, to CSS Color Level 4. This is a tribute to Eric Meyer's daughter who recently passed away and a mark of support from all the Web community to Eric. I requested to ping Eric to be absolutely sure he is ok with this; he responded "he was honored by the gesture, and would love to accept it".


I'm glad we work in a field that isn't so stodgy that lovely tributes like this are possible.


Direct Link to ArticlePermalink



rebeccapurple = #663399 is a post from CSS-Tricks








Donnerstag, 19. Juni 2014

Prefilling Forms with a Custom Bookmarklet




CSS-Tricks





Prefilling Forms with a Custom Bookmarklet



The following is a guest post by Adam Lichtenstein. Adam works at Wufoo, a web app for building web forms, so you can imagine the need for testing forms is at least double what the rest of us need. Adam took a different road than I took, so I'll let him share.



Like most devs, I spend a lot of time manually testing the user experience on the site I work on. Unit and integration tests are great, but there's no easier way to find a pain-point on your site than to do it a thousand times.


With forms, this can get tedious, fast.


That's the situation I found myself in a couple of months ago when we were adding the British Pound to our checkout currencies in Wufoo. I had multiple fields to fill out with names, emails, addresses, credit cards. You name it. And of course, a lot of the data had to be unique.



So I built a JavaScript bookmarklet to help the team quickly fill in our checkout forms for testing.


I chose a bookmarklet because:



  1. I can distribute it quickly and easily

  2. I can push updates without the users having to do anything

  3. I can run them on any environment without changing the code


You can build and distribute a Javascript bookmarklet really quickly by creating a Pen on CodePen and adding this snippet into an href:


<a href="javascript: **js goes here** "></a>

Your user only needs to drag the link into their bookmarks bar. Then click on it any time they want to run that code on the current page in the browser.


For this project, I'm going to lean on jQuery to keep the code lean and cross-browser friendly. If anyone wants a vanilla version, let me know in the comments and I'll be happy to put something together.


I also want to insert random data for most of the fields, so I'm going to use a great library out there called Faker. We'll use the JavaScript implementation here.


Building the Bookmarklet


We could put our code directly into the snippet. But besides being cleaner and more maintainable, we want to be able to update that code without being forced to update the actual bookmarklet. So instead, lets reference an external file.


We'll start with our snippet code:


<a href="javascript:
(function(d) {
var body = d.getElementsByTagName('body')[0],
script = d.createElement('script');
script.src = '//localhost.com/pathtomyfile.js';
body.appendChild(script);
}(window.document));
">My Javascript Bookmarklet</a>

We're using JavaScript to append a script tag to the body, and adding the path to our file inside. If you are testing on an https secure page, you will want to make sure your script is also https. Otherwise some browsers will throw a security error.


Note: You'll probably use a localhost version of the file while you're in development and replace it with a production version when you're ready to share.


The Prefilling Script


Now that we have our bookmarklet ready to load a script file of our choice. Lets make that script file.


It's super important to make sure your own code doesn't conflict or break anything on the original page. So we'll wrap the whole thing in a Self Invoking Anonymous Function. That will use scope to make sure our variables don't change anything else on the page.



(function(win, doc, $, undefined) {
'use strict';

// Don't run if jQuery isn't loaded
if (typeof window.jQuery === 'undefined') {
return;
}

// Our code will go here.

}(window, window.document, window.jQuery));

I like Chris' randomize function from the original article. Lets use it to quickly generate random numbers when we need them.


var _rand = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

Next, lets load up the FakerJS script. Since we've decided we'll use jQuery as a dependency, we can just use $.getScript which will return a promise when its done.


$.getScript('//cdnjs.cloudflare.com/ajax/libs/Faker/0.7.2/MinFaker.js')
.done(function() {
// run our functions from here
})
.fail(function() {
win.console.error('ERROR: FakerJS not loaded!');
});

Now that we have access to Faker, we can use its methods to generate all kinds of fake names, emails, addresses, etc.


We'll make a constructor function to load that data so we can reuse it if we want to in the future.


var FormData = function(faker) {

this.faker = faker;

this.randomWord = faker.Internet.domainWord();

this.username = 'fake_' + this.randomWord;
this.username += _rand(100,9999);

// set this value to your password specifications
this.password = 'pass1234';

this.name = faker.Name.findName();

this.address1 = faker.Address.streetAddress();
this.city = faker.Address.city();
this.state = faker.random.br_state_abbr();
this.zip = faker.Address.zipCode();

// Chris' actual credit card number
this.cc = '4242 4242 4242 4242';
this.exp1 = _rand(1,12);
this.exp2 = _rand(14,22);
this.cvv = _rand(100,999);

};

I'd like to make certain field types like checkboxes and select boxes random. So lets extend the FormData object with some functions.


// Randomly select dropdown
FormData.prototype.randomizeSelect = function(el) {
var $el = $(el),
len = $el.find('option').length - 1;

$el.children('option')
.prop('selected', false)
.eq( _rand( 1,len + 1 ) )
.prop('selected', true);
};

// Randomly select radio button
FormData.prototype.randomizeRadio = function(radios) {
radios = radios.not('[type="hidden"]');
var len = radios.length;

radios
.prop('checked', false)
.eq( _rand( 0, len - 1 ) )
.prop('checked', true);
};

// Add some lorem text for textareas
FormData.prototype.randomizeParagraph = function(el) {
$(el).val(this.faker.Lorem.sentence(5));
};

// Randomize all checkbox fields
FormData.prototype.randomizeCheckbox = function(el) {
var $el = $(el);

$el.prop('checked', false);

if (_rand( 0,1 ) === 0) {
$el.prop('checked', true);
}
};

FormData.prototype.randomizeEmail = function(el) {
// if we want different emails for all email fields, we can modify this
$(el).val('chriscoyier+' + this.randomWord + '@gmail.com');
};

And last, we just need to bind the data to the fields on our form. We'll use jQuery to grab each of the fields, or field types where we can, and replace the value without data object. This gives us a nice separation between creating the data, and populating it.


var fillForm = function() {
data = new FormData(window.Faker);

$('#name').val(data.name);
$('#username').val(data.username);
$('#cc').val(data.cc);
$('#exp-1').val(data.exp1);
$('#exp-2').val(data.exp2);
$('#cvv').val(data.cvv);
$('#address').val(data.address1);
$('#city').val(data.city);
$('#state').val(data.state);
$('#zip').val(data.zip);
$('#pw').val(data.password);
$('#pw-repeat').val(data.password);

data.randomizeRadio($('[name="radio-choice"]'));

// Randomize all select boxes
$('select').each(function() {
data.randomizeSelect(this);
});

// Randomize all checkboxes
$('input[type="checkbox"').each(function() {
data.randomizeCheckbox(this);
});

// Randomize all textareas
$('textarea').each(function() {
data.randomizeParagraph(this);
});

// Randomize all emails
$('input[type="email"').each(function() {
data.randomizeEmail(this);
});

};

You could also call submit on the form at the end to automatically send the data if you wanted. It's just a matter of preference.


$('#form').submit();

Conclusion


That's about all it takes to get a quick and dirty random data form filler in a javascript bookmarklet.


There's definitely a few ways we could improve on this. ut when you're in a time crunch, it can definitely do the trick.


Check out Inline Copy Editor if you want to see another JavaScript bookmarklet I open sourced for the SurveyMonkey design team.


Hope this helps someone out. Reach out if you have any questions.


Demo


See the Pen 2cde9271cbfbeb48532c2041dbea9c5c by seethroughtrees (@seethroughtrees) on CodePen.




Prefilling Forms with a Custom Bookmarklet is a post from CSS-Tricks








Dienstag, 17. Juni 2014

Use Cases and Requirements for Element Queries




CSS-Tricks





Use Cases and Requirements for Element Queries



This is a perfect example of making a case for new language features. Not just a vague "element queries! that would be awesome!" but laying out a real-world scenario, what we have to do to achieve it now, and why that's not ideal. Of course there are big challenges (see this and this) but those debates can be held elsewhere and not muddy the "why we need it" explanation.


Direct Link to ArticlePermalink



Use Cases and Requirements for Element Queries is a post from CSS-Tricks








Montag, 16. Juni 2014

Async Attribute and Scripts At The Bottom




CSS-Tricks





Async Attribute and Scripts At The Bottom



A reader recently wrote in and (essentially) asked me:


Is there any reason to use the async attribute when the script is already at the bottom of the page?


I'm not a master at this stuff, but this is how I understand it...



What he was talking about was this:


  <script async src="/js/script.js"></script>

</body>

We've covered this before a bit. It's extra-interesting to re-visit now though, because the async attribute is now really the only recommended way to be doing async scripts.


So, is there any reason to use the async attribute when the script is already at the bottom of the page?


Short Answer


No.


Longer Answer


What you are trying to prevent with the async attribute is parser blocking. If you use the async attribute, you are saying: I don't want the browser to stop what it's doing while it's downloading this script. I know that this script doesn't really depend on anything being ready in the DOM when it runs and it also doesn't need to be run in any particular order.


If you load the script at the bottom of the page, the parser is effectively done already, so blocking it isn't a big deal. You're essentially already deferring the script, which is kinda like a more hardcore async. See comparison.


It might even be a little dangerous.


If you were just operating under the assumption that async = good, you might do something like:


  <script async src="/js/libs.js"</script>
<script async src="/js/page.js"</script>

</body>

That could be bad news, because chances are "libs.js" has dependencies for "page.js", but now there is no guarantee the order in which they run (bad).


It's mostly third-party thing.


Third-party scripts are the big use-case for async scripts. They (the third-parties) can't control where you put that script on your page, so they are typically designed to work no matter when/where they load anyway. You also can't control third-parties (that's what a third-party is, Wayne) so making darn sure they don't slow your site down is ideal.


Is there any other use-cases?


I guess if you really wanted to get the download started on one of your own scripts right away, and it didn't matter when it ran, you could put it in the <head> and async it.


I might be kinda wrong.


I tend to screw up these JavaScript advice posts, so if I did, let's talk about it in the comments and I'll make sure the content of this post reflects the best information.




Async Attribute and Scripts At The Bottom is a post from CSS-Tricks








Samstag, 14. Juni 2014

About That Small Business Website Of Yours




CSS-Tricks





About That Small Business Website Of Yours



Here's a (lightly edited) real email exchange I just had with someone in my family. I thought it would be worth sharing.



Hi Chris,


I understand that you have been talking with [another family member] about our website. I expressed to him that I would like to have the ability to change, expand, and improve it occasionally. He said that you would be willing to help me learn to do this. My concern with our web page is that, while it is pretty, doesn't entice people to buy our services as well as I would like.


The site is www.adcreate.com. Let me know what you think. I would really appreciate any advice you can share to point me in the right direction.


- Family Member of Chris'


Hey [Family Member],


This is my advice I give to everybody in your position: get off the setup where you have a "web designer person" and they are in control of everything and you have to go through them for all changes. I can't even count the number of times I've seen that go south.


The web has grown up a bit and there are services that allow you to build your own site that do a very good job at it. Then not only are you in control, but:



  • The site will look great. The templates they provide are usually quite good and easy to customize.

  • They typically use what is called "responsive design" meaning the design will look good and work on things like the web browser on your phone, or an iPad. Not that "zoomed out" thing that can be a pain in the butt to use.

  • It's inexpensive. Around the $20/month level.

  • You do it yourself in a matter of hours. Especially with pre-existing content like you have. I've seen non-webby friends do it many times and do a great job. Here's an example.


The sites I typically think of are:


http://virb.com/


and


http://www.squarespace.com/


But there are plenty more. I don't have any particular favorites, but if you find yourself looking around for site-building sites like these and find one you like, feel free to send it to me for vetting.


A lot of their "demo" sites are pretty art-y, but remember those are just demos and you can generally customize a theme very much to your liking, including choosing all your own photos, backgrounds, colors, and of course the content on each page. Here's an example of a printer website that I think does a good job.


The sites I mentioned both also have eCommerce stuff built in, so perhaps that might work for you for actually taking sales if that is a direction you want to go.


It feels a little weird to say all that as a "web designer person" myself. Like I'm shooting myself in the foot somehow, but I don't think that's the case. People like me work on websites that need to be very custom or are much bigger and need a dedicated team.


There is also a middle of the road decision you could make here. You could keep your "web designer person" but insist that they help you getting your site onto a platform that empowers you to do all these things you want to do.


Remember that a website is just a communication tool. The most effective sites aren't just piles of loose content, but are dead-clear in their message and have carefully curated content that is a reflection of what you want to say and what visitors want to see. You don't have any special web skills for that.




About That Small Business Website Of Yours is a post from CSS-Tricks








Freitag, 13. Juni 2014

Cascading SVG Fill Color




CSS-Tricks





Cascading SVG Fill Color



One time someone told me their biggest problem with SVG icons is that they didn't match the color of text they were by. In fact it was such a big problem for them, that despite seeing the advantages of SVG icons they were sticking with icon fonts. I didn't think of it at the time, but there is a pretty easy solution for this.



The idea is to use the currentColor value in CSS to pass that text color through to the SVG shapes. For instance:


<h1>
<svg viewBox="0 0 32 32">
<use xlink:href="#icon-phone"></use>
</svg>
Call Me
</h1>

h1 {
color: blue;
}
h1 svg {
fill: currentColor;
}

You can simplify this and let the fill cascade to the SVG:


h1 {
color: blue;
fill: currentColor;
}

So fill cascades eh? Pretty neat. Why don't we just do this then if it's that easy:


body {
fill: currentColor;
}

fill only affects SVG anyway, so it won't be doing anything we don't want it to do, and it's easily overridable by a more specific selector anyway.


The trouble is that doesn't quite work as is.


Take this example, which is just our original example inside the <body>:


<body>
<h1>
<svg viewBox="0 0 32 32">
<use xlink:href="#icon-phone"></use>
</svg>
You'd think the SVG would fill blue too?
</h1>
</body>

Then:


body {
fill: currentColor;
color: red;
}
h1 {
color: blue;
}
svg {
border: 5px solid currentColor;
}

What is the currentColor at the <svg>? blue, right? Because color cascades (is inherited). We can see that's true, because the border on that svg will be blue. But the icon itself (which is really a drawn <path>) will be red.


Weird, I think.


It's not a huge deal though, because you can just:


svg {
fill: currentColor;
}

And that will ensure it snags the color from whatever you would normally expect it to. You can also apply the fill to the use, path, symbol, circle, rect, etc, but hitting the svg just kinda covers it all (which is nice for simple one-color use cases).


See the Pen lcDBd by Chris Coyier (@chriscoyier) on CodePen.




Cascading SVG Fill Color is a post from CSS-Tricks








Donnerstag, 12. Juni 2014

Everything You Need to Know About the CSS will-change Property




CSS-Tricks





Everything You Need to Know About the CSS will-change Property



Sara Soueidan lets us know translateZ(0); is out and will-change: transform; (et al) is in. The general tips being: use sparingly, apply before you need it, be honest about what really needs it.


There is some backlash about this, mostly centered around the idea that browsers should be handling this for us. The opposition saying it's too hard for browsers to know, so this is essentially browsers and devs meeting in the middle. Sounds a lot like the responsive images debate, doesn't it?


Here's a good conversation about it.


Direct Link to ArticlePermalink



Everything You Need to Know About the CSS will-change Property is a post from CSS-Tricks








Mittwoch, 11. Juni 2014

Sharing Data Between Sass and JavaScript with JSON




CSS-Tricks





Sharing Data Between Sass and JavaScript with JSON



Imagine you have a set of breakpoints you have defined for your design that adjust the layout. Now you need to mimic those breakpoints in JavaScript, because you are choosing to load some dynamic content at that breakpoint. Now you're maintaining that breakpoint at two different places in your code. Inefficient and error prone.


This idea by Nate Hunzaker allows you to define those breakpoints in a JSON file that can be used by Sass as well as JavaScript. And not just breakpoints, but any data you might need in both places: colors, layout information, perhaps user preferences?


Direct Link to ArticlePermalink



Sharing Data Between Sass and JavaScript with JSON is a post from CSS-Tricks








Dienstag, 10. Juni 2014

New Poll: Typing Skills




CSS-Tricks





New Poll: Typing Skills



Reader Hendrik Maus wrote in asking me about how I value typing skills and suggested running a poll on it. Good idea, Hendrik! I love polls that unearth some interesting data around developer opinions and skills. There are lots of ways we could ask it, but we're going to try this way:


How much do you value your keyboard typing skills?


Not so much "how good are you?" but "how important do you think your skill is?" It was kinda tough to phrase right, but we'll just go with it.



The poll is in the sidebar of the site, and you can answer between 1 (not valuable) and 10 (extremely valuable).


The data will be interesting, but the conversation we can have here might be even more interesting. When Hendrik wrote in, I was curious what his thinking was. Here's some food for thought:



  • Would you be better at your job if you were a better typist? We do a lot of typing, don't we? Perhaps a new sense of confidence could be found?

  • Do you have an unusual style? Of your own invention? Something established like Dvorak?

  • Do you practice? How? Special software? Personal challenges?

  • Do you think if you did find time to practice, the gains would be worth it? How much time could be saved from not needing to correct as many errors?

  • Do you think you naturally level up over time? Or is there a plateau you can't pass without dedicated practice?

  • Is speed or accuracy more important? Particularly with programming?

  • Is programming much different than other types of typing? There sure are a lot more weird characters. Would you have to train differently to get better at programmer style typing?

  • Are there health concerns? Does better typing skill mean less chance at stuff like RSI?




New Poll: Typing Skills is a post from CSS-Tricks








Montag, 9. Juni 2014

Poll Results: Sharing Buttons




CSS-Tricks





Poll Results: Sharing Buttons



A poll has been running here regarding sharing buttons. We asked it this way:


This best describes how I share links on my social media site(s) of choice:


12.5 thousand CSS-Tricks visitors voted. The results are in! Here are the choices and results:



  • 60% I don't ever use sharing buttons. I share my own way.

  • 31% I can go either way.

  • 9% I typically only share pages that have sharing buttons.


Of course, these are CSS-Tricks visitors. You can decide how relevant that is for yourself. I like to think that front end developers aren't entirely different from other human beings.


One way to look at it is that 60% of people (at least say) that they would never use them even if they were there. That's a pretty strong case that they could be considered visual clutter. You're already fighting to get a tiny percentage of people to share, and to know that you're trying to squeeze those from just 40% of visitors feels a bit weird.


But that's only considering direct use. There is the "remind" consideration, in which showing people a share button might remind them to share regardless if they use the actual button or not.


Then there is the performance consideration. There are ways to be responsible about the loading of sharing buttons, but any way you cut it adds weight to the page. There is always a risk you lose visitors from having them. I've never seen a statistic in which weightier pages garner more viewers. It's always more speed = more visitors.


The last big one for me is aesthetic concern. Even if you can make them visually nice, the presence of sharing buttons at all always feels a little cheap to me. It never makes a page feel more classy, anyway. And that leads into "quality of shares". We all know not all shares are considered equal. I don't have any data on this but it seems like you'd be likely to get higher quality shares from a classier page. From people who are good enough at social media to share things they actually like in a classy way.


From the comments on the original post:


Nate Green:


I typically don't use share buttons because I've found that they don't share things in a way that I’d like them to. Too many that I've tried either insert their own robotic message, use a crappy spammy-looking thumbnail, or link to a page that wasn't the one I was trying to share.


zzzzBov:


If a user doesn’t know how to share pages on my site without a share bar, they’re not really in my target audience


Jon Hobbs:


I think sometimes developers tend to project their own preferences (and skills) onto their users.


Yes, we all know how to copy and paste a URL into Facebook, or use a Chrome extension, but a significant proportion of our users are likely to share more if we make it easy for them.


Lindsey:


Personally, I do like to include buttons for my own site and most my clients’ sites. Not because I think the value of the content is worthy of being shared all the time, but because someone else may think it is.


Eloise:


One site I was on yesterday had over 150k likes on Facebook for the homepage, their best selling item (sells about 125 units per day) has 3 likes!


Shai:


I usually don’t use share buttons because I want to have more control over the things I share. I’m also not an serial sharer so the little extra time it takes me to “craft’ the share doesn’t matter to me that much.


Chase:


Not only am I far more likely to share via a share button on mobile, but I’m far less likely to share if there isn’t one. Sometimes copy/pasting the url into a different app is just a little too tedious when I’m busy and on the move.


Shaw:


Having a custom link allows you to tweak the buttons to match your site, preventing any garish look, and won’t display how many times it’s been liked or shared (embarrassing low numbers). If you’re only adding a few icons (which you may already be using elsewhere) and <a> tags, there’s barely any performance implications.


At the time of this writing, and I change my mind a lot on this subject, I'm with Shaw. I'm using custom anchor links for sharing buttons. Simple custom look, no performance penalties, there if people need them (perhaps most useful on mobile).




Poll Results: Sharing Buttons is a post from CSS-Tricks








Freitag, 6. Juni 2014

Universal overflow: auto;




CSS-Tricks





Universal overflow: auto;



Greg Smith isn't advocating we start just slapping on * { overflow: auto; } into all our existing projects. But if we start a project with this, there are a number of advantages, like not needing to use a clearfix or worrying about collapsing margins. Of course sometimes you want a different overflow behavior, but you can just set it like you would anyway.


See the comments about inheriting the value rather than setting it.


Sometimes these things catch on, just look at box-sizing. And sometimes they don't.


Direct Link to ArticlePermalink



Universal overflow: auto; is a post from CSS-Tricks








Donnerstag, 5. Juni 2014

Prefill Your Own Forms in Dev




CSS-Tricks





Prefill Your Own Forms in Dev



There is a good chance there is a bunch of forms on the websites you work on. Login and signup forms, payment forms, contact forms, comment forms, etc. It's a good idea to test these forms. Certainly automated tests are a good idea. Backend tests that process the form data and test the results. Frontend tests that test the functions there are doing what you expect.


But then there is manual testing. Like, I want to test this with my eyeballs and my keyboard and mouse and emotions and stuff. That's probably the most common type of testing for designers. Certainly just filling out the forms by hand is a good idea, but doing that over and over gets so tedious you (gasp) might just not do it very often.


Perhaps we can just toss a little bit of code on our sites to prefill them when we need.



Prefill from the Template


One possibility is to prefill all the time from the template itself. For instance, you could check if you're on the development domain and then prefill the value. Like:


<?php
if ($_SERVER['HTTP_HOST'] == "mysite.dev") {
$prefill = true;
}
?>

<input type="text"
name="name"
id="name"
<?php if ($prefill) { ?>
value="Chris Coyier"
<?php } else { ?>
value=""
<?php } ?>
>

Or the Rails-y way:


<input type="text" 
name="name"
id="name"
<% if Rails.env.development? %>
value="Chris Coyier"
<% else %>
value=""
<% end %>
>

The problem with this is that you always see the form filled in on development, which isn't how your users encounter it. I prefer to leave the form how the users see it, then optionally fill it in on-demand.


Prefilling with JavaScript


Using the same test-if-development stuff as above, we can insert a new script onto the page to do the prefilling.


<?php if ($_SERVER['HTTP_HOST'] == "mysite.dev") { ?>
<script src="/assets/development/form-prefiller.js"></script>
<?php } ?>

There are a couple of ways you could go about it:



  • Automatically prefill fields it finds

  • Insert some buttons to prefill

  • Just have some public functions you can manually call from the console


There isn't much advantages to using JavaScript if you're going to auto-prefill. For the purposes of this demo, I'll make buttons. In reality, I just leave it to the console.


A very simple version of the script might be like:


var PrefillMachine = {

prefillCorrectly: function() {
$("#name").val("Chris Coyier");
}

}

Then anytime you're on the page with the form, you just open the console and type:


PrefillMachine.prefillCorrectly();

Or if you had some buttons on the page:


var PrefillMachine = {

init: function() {
this.bindUIActions();
},

bindUIActions: function() {
// Probably even best to insert this button with JS
$("#prefill-correct").on("click", this.prefillCorrectly);
},

prefillCorrectly: function() {
$("#name").val("Chris Coyier");
}

}

PrefillMachine.init();

Prefill Values and Types


It's one thing to just prefill some set values, but you might want to randomize it a bit. For instance, it doesn't help much to prefill the same username over and over on a signup form, because your system will likely reject it as a duplicate. So let's randomize a bit!


In our PrefillMachine object, we can make a function to give us a random string:


_makeId: function()  {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

for (var i=0; i < 5; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}

return text;
},

When we call that, it will give us stuff like eQthY, Jv1ea, or Cmy4g. Pretty unlikely to repeat.


So if we're prefilling a name and username, for instance, we might make our prefilling function be like:


prefillCorrectly: function() {

var id = this._makeId();

$("#name").val("name_" + id);
$("#username").val("username_" + id);

...

We're just prefixing those randomized values so they would be easy to find in a database if we wanted to wipe them out or something.


Testing an email address? Perhaps use that randomized value as an extension to a gmail address. That way it's unique, but you'll still get the email.


$("#email").val("chriscoyier+" + id + "@gmail.com");

What about checkboxes, radios, and selects? Might be nice to randomize the choices there. We can make a super quick random number generator:


_rand: function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

Then say there was a radio button group with two choices, we could turn them both off, select one at random, and turn it back on:


$("input[name='radio-choice']")
.prop("checked", false)
.eq(this._rand(0, 1))
.prop("checked", true);

Similarly easy with a select:


$("#select-choice")
.find("option")
.prop("selected", false)
.eq(this._rand(0, 2))
.prop("selected", true);

Randomize a street address?


$("#address").val(this._rand(1000, 9000) + " Super St.");

You get the picture.



Prefilling Incorrectly


Perhaps just as useful as prefilling a form correctly, you can test error states by prefilling incorrectly. Just make another function for doing that:


prefillIncorrectly: function() {

// Empty should be invalid
$("#name").val("");
$("#username").val("");

// Space should make invalid
$("#email").val("jim @jim.com");

// Force them not to match AND one is blank.
$("#pw").val("123");
$("#pw-repeat").val("");

// Turn both off.
$("input[name='radio-choice']")
.prop("checked", false);

// Not enough numbers
$("#cc").val("424242424242");
// Values are wrong
$("#exp-1").val("50");
$("#exp-2").val("02");
$("#cvv").val("abc");

// Left unchecked
$("#agree-terms").prop("checked", false);

},

Then call it as you will. Then you can submit and see if your error-handling system is working properly.



You could probably even use all this as part of an end-to-end testing kinda thing, but I'll leave that for smarter folk.


Demo


Here's an example of everything:


See the Pen pzKtx by Chris Coyier (@chriscoyier) on CodePen.




Thanks to Tim Sabat for introducting me to this idea. He came up with it and implemented it on CodePen for us to make testing for all of us easier.




Prefill Your Own Forms in Dev is a post from CSS-Tricks








Mittwoch, 4. Juni 2014

Inverse trigonometric functions with Sass




CSS-Tricks





Inverse trigonometric functions with Sass



I link this up not because I think we all need to know trigonometry in our day to day CSS worker lives, but because: holy crap Ana Tudor does amazing stuff with Math and Sass which results in some capital-A Art and I'm sure there are more of you out there that would be interested in following her work.


Direct Link to ArticlePermalink



Inverse trigonometric functions with Sass is a post from CSS-Tricks








Dienstag, 3. Juni 2014

SVG `symbol` a Good Choice for Icons




CSS-Tricks





SVG `symbol` a Good Choice for Icons



You could design an icon set where the icons all had the exact same aspect ratio. But that's probably not typically going to be the case. The container around a little beaker icon might be tall and narrow. The container around a little fish perhaps short and long. You probably shouldn't have to think too much about that, but unfortunately you kinda have to when you use an SVG icon system as I've described in the past, because you need to use the viewBox attribute to describe that container/aspect ratio.


An improvement is to use the <symbol> element in SVG instead of directly referencing shapes (or a <g>), because you can define the viewBox directly on the <symbol> and then not need one when you <use> it later in an <svg>.


An example is in order.



Here's two icons with very different aspect ratios, as you can tell from the artboard in Illustrator.



We could adjust them to all be placed within a consistent aspect ratio, but I find it's more flexible and workable to know that your icons edges are right where the shapes stop, not with an arbitrary amount of white space around them.


The "Old" Way


If we go the <defs>-block route, we might combine them into:


<svg>
<defs>
<g id="shape-icon-1">
<!-- all the paths and shapes and whatnot for this icon -->
<g>
<g id="shape-icon-2">
<!-- all the paths and shapes and whatnot for this icon -->
<g>
</defs>
</svg>

Then use them like:


<!-- These viewBox's better be right or the icons won't look right! -->

<svg class="icon" viewBox="214.7 0 182.6 792">
<use xlink:href="#shape-icon-1" />
</svg>

<svg class="icon" viewBox="0 26 100 48">
<use xlink:href="#shape-icon-2" />
</svg>

That puts a good amount of onus on the implementer to get those viewBox attributes correct in the markup. That's one reason why might want to try and get all those icons at a consistent viewBox="0 0 100 100" (or something), but then we have that kinda arbitrary whitespace thing going on.


The "New" Way


Enter Fabrice Weinberg and TxHawks. Fabrice works on grunt-svgstore, a Grunt plugin for creating the SVG sprites from a folder of SVG files. This kind of thing makes the SVG icon workflow quick and easy. That is, except for the fact that you need to know that dang viewBox for each icon before you use it.


TxHawks suggested having grunt-svgstore at least put data-* attributes on the <g> elements that wrap each icon, so there could be programmatic access to what it is supposed to be. But unfortunately SVG doesn't allow those (it would have probably worked, but might as well make a build tool spec-compliant). It doesn't matter though, because soon after, they suggested using <symbol> instead, which turns out to be quite a good idea.


Instead of using <g> to wrap all the icon shapes, use <symbol>, like this:


<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">

<symbol id="beaker" viewBox="214.7 0 182.6 792">
<!-- <path>s and whatever other shapes in here -->
</symbol>

<symbol id="shape-icon-2" viewBox="0 26 100 48">
<!-- <path>s and whatever other shapes in here -->
</symbol>

</svg>

Note that the viewBox is defined for each icon and as you're defining it as opposed to when you're using it. That means using it becomes easier:


<!-- We ain't even need no viewBox round here. --> 

<svg class="icon">
<use xlink:href="#shape-icon-1" />
</svg>

<svg class="icon">
<use xlink:href="#shape-icon-2" />
</svg>

Easier, and less error prone.


And it gets better: you can add <title> and <desc> tags in the symbol as well, meaning the accessibility stuff is baked in as you use it.


<symbol id="icon1" viewBox="original-file's-viewBox">
<title>original-file's-title</title>
<desc>original-file's-desc</desc>

<!-- <path>s and other shapes -->

</symbol>

grunt-svgstore does this now, thanks to TxHawks and Fabrice!


Why <symbol> is better for icons


Just to put a point on it:



  1. The viewBox can be defined on the symbol, so you don't need to use it in the markup (easier and less error prone).

  2. title and desc attributes can be added there as well, making accessibility easier to do right.

  3. Symbols don't display as you define them, so no need for a <defs> block.

  4. This is probably what <symbol> was invented for anyway.


Demo


It works:


See the Pen Hwcxp by Chris Coyier (@chriscoyier) on CodePen.




SVG `symbol` a Good Choice for Icons is a post from CSS-Tricks








Montag, 2. Juni 2014

Using Encapsulation for Semantic Markup




CSS-Tricks





Using Encapsulation for Semantic Markup



The following is a guest article by Chris Scott. Chris takes us through a great use case for the Shadow DOM. As designers, we may want to style something in a certain way, but sometimes end up having to go to war with HTML, CSS, and JS to get it done. And even then, the results can be weighty, hacky, and unsemantic. Shadow DOM might be able to save us from that, giving us a fresh place to use whatever HTML we need (need 20 empty elements? No problem!) without exposing that mess to the actual DOM (which would suck for accessibility, semantics, etc.)



File inputs are notoriously hard to style. Let's say you want to use an SVG icon instead of the default button-and-filename styling.


onjective

That is not a trivial styling change. Input elements are "no content" elements, i.e. an element that doesn't have a closing tag. Thus, there is nowhere to put an SVG element "inside" of it. So how might you go about this?


Well, let's take a progressive enhancement approach and start with the basic functionality:


<form>
<input type="file"></input>
</form>

What do we get out of the box? Semantically, it's very descriptive: there's an element that allows the user to input a file. It's also functional: if you click on it a file system dialogue opens.


Now let's think about adding the icon. You could put the image near the input, perhaps using z-indexes and transparent inputs to retain the functionality of the input (like this). This approach is okay semantically (you have an input and an image) but it definitely feels hacky and is more difficult to test. Alternatively, you could use an <img> tag and drop the <input> altogether, but then you have all the issues of replicating the file input's functionality and you have lost a bunch of meaning from the markup.


(There are other ways you could go about this as well. For instance a label-with-hidden-input, but for the sake of getting to the point here, let's move on.)


Shadow DOM


A better approach, in my opinion, is using Shadow DOM. Shadow DOM is one of the ingredients to Web Components, and you can read up on all that here. I just want to talk about its semantic benefits, for now.


Shadow DOM is described in the W3C draft spec as functional encapsulation or functional boundaries. That means we can encapsulate some design and pin it to an existing node on the DOM tree (called the Shadow Root). Returning to our example:



var button = document.querySelector(&#x27;input[type=&quot;file&quot;]&#x27;);
var shadowDom = button.webkitCreateShadowRoot();
shadowDom.innerHTML = &quot;&lt;div&gt;Hello from the other side&lt;/div&gt;&quot;;

See the Pen gHEei by chrismichaelscott (@chrismichaelscott) on CodePen.



Take a look at the result in the Pen above. This may look like a long-winded way of changing some HTML but that's not actually what happened. If you were to "inspect element" in your browser you would still see the original file input - no sign of a div at all. More to the point, if you click on the string the browser will pop up a file system dialogue. This is the crux of encapsulation: from the outside the input is still an input but if you traverse the functional boundary then it's not an input at all, it's a string. That means that we can make an input (or any other tag, for that matter) render in any way want. We can set the inner HTML of the Shadow Root to be any valid HTML and it will render as such. Including, of course, adding SVG.



var button = document.querySelector(&#x27;input[type=&quot;file&quot;]&#x27;);
var shadowDom = button.webkitCreateShadowRoot();
shadowDom.innerHTML = &quot;&lt;img src=\&quot;https://s3-eu-west-1.amazonaws.com/chrisscott/codepen/iconmonstr-archive-7-icon.svg\&quot; alt=\&quot;Select file\&quot;&gt;&lt;/img&gt;&quot;;

See the Pen jiqoh by chrismichaelscott (@chrismichaelscott) on CodePen.



Clearly that isn't a particularly good looking alternative, but it's a start. And the HTML is simple and semantically correct. To take this further let's look at another tool in the HTML5 Web Components toolbox that's useful for this kind of thing: template tags.


Templates


Template tags are basically a way of building HTML that is not rendered. The cool thing about templates is that you can use JavaScript to inject the DOM from a template into an element elsewhere in the document. In this case, we can define a template for our fancy vector image file input and use that to define the Shadow DOM for actual input tags. Here's a suitable template:


<template id="file-button-template">
<style>
img {
padding: 6px;
border: 1px solid grey;
border-radius: 4px;
box-shadow: 1px 1px 4px grey;
background-color: lightgrey;
width: 30px;
cursor: pointer;
}
img:hover {
background-color: whitesmoke;
}
</style>
<img src="https://s3-eu-west-1.amazonaws.com/chrisscott/codepen/iconmonstr-archive-7-icon.svg" alt="Select file"></img>
</template>

Bringing it all together


The template element can be placed into the head of a document, and I think that's a nice place for it. The following Pen has the template we just defined in the head. If you open it on CodePen.io you can see the template by clicking the cog in the top left of the HTML panel.


See the Pen jghes by chrismichaelscott (@chrismichaelscott) on CodePen.


Pretty good, I reckon. Semantically, it's exactly the same as the vanilla HTML but it is visually completely bespoke.


Browser support, polyfills and graceful degradation


There's some bad news (then more bad news and then a little, tiny glimmer of good news) in terms of support for Shadow DOM in browsers.


The first piece of bad news is that editing Shadow DOM is, currently, only supported in WebKit/Blink browsers, using the prefixed element.webkitCreateShadowRoot() method. Firefox 30 should support Shadow DOM as well, though.


Bad news number two: Polyfils may not support this use case - certainly Polymer doesn't. In the case of the Polymer platform, to understand why the polyfill doesn't behave as the native implementation does one needs to understand the mechanics of the polyfill. Essentially, the Polymer platform performs it's encapsulation by replacing native DOM nodes with wrappers. These wrappers emulate the behaviour of actual DOM nodes; for example, you can set the innerHTML of the wrapper as you would a native node. The wrappers maintain the so-called light DOM and shadow DOM. In terms of encapsulation, this works fairly well as the wrapper can intercept calls on the light side (such as the children getter) and hide the shadow DOM.



var light = document.querySelector(&quot;div&quot;);
var template = document.querySelector(&quot;template&quot;);

light.createShadowRoot().innerHTML = template.innerHTML;

document.querySelector(&quot;code&quot;).innerHTML =
light.innerHTML

See the Pen FCknf by chrismichaelscott (@chrismichaelscott) on CodePen.



In this example, the retieved inner HTML of the "light" DOM show the encapsulation working (there is no h1 tag). However, the polyfill has not used actual Shadow DOM (otherwise it wouldn't be a polyfill!) and you can verify that if you inspect the first div from the results. In the DOM, you will see, there is an h1 tag - not hidden in the Shadow DOM, just there. That's because, underneath the wrapper, the Polymer platform is just manipulating the regular DOM tree as there is no shadow root.


In terms of the file input SVG icon that is not good. If one were to run the demo of the file input with the Polymer polyfill, as with the previous example, it would merely insert the img tag as a child of the input. If you recall, that is not allowed. An input is a void element and has no permitted child elements, so the browser will just ignore the img and style elements as invalid children. Here is a fork of the 'pen illustrating the issue; again, inspect the element and you can verify that the polyfill has added the template as children of the input.


And so, to the promised "tiny glimmer of good news"... Even though support is limited at the moment, I still think that it is justifiable to start using Shadow DOM to do things like this, now. Why? If your user's browser doesn't support Shadow DOM it will just render a normal file input. That's not a bad thing and considering the complex (read: hacky) alternatives I think Shadow DOM should be considered a plausible choice.


Notes on Shadow DOM, Web Components, etc


There are a huge number of use-cases for Shadow DOM and the related Web Components. This article has completely overlooked the advantages of encapsulation in terms of developing frameworks and widgets. For those interested it's worth reading the specs and getting to grips with Polymer.




Using Encapsulation for Semantic Markup is a post from CSS-Tricks