{"id":2479,"date":"2012-08-02T10:22:50","date_gmt":"2012-08-02T16:22:50","guid":{"rendered":"http:\/\/bililite.com\/blog\/?p=2479"},"modified":"2012-08-03T15:13:53","modified_gmt":"2012-08-03T21:13:53","slug":"understanding-before-and-after","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2012\/08\/02\/understanding-before-and-after\/","title":{"rendered":"Understanding <code>:before<\/code> and <code>:after<\/code>"},"content":{"rendered":"<script>$('<style> .before-test:before { content: \"label: \"; } .labeled td:before { content: attr(data-label); } .labeled thead { position: absolute !important; clip: rect(1px, 1px, 1px, 1px); }<\/style>').appendTo('head');<\/script>\r\n<p> I wanted to use the <a href=\"http:\/\/www.w3.org\/TR\/CSS21\/generate.html#before-after-content\">CSS pseudoelement :before<\/a> for manipulating input elements. I had <code class=\"language-html demo\">&lt;input class=\"before-test\"\/&gt;<\/code>, and I wanted to use CSS to add a label before the element on small screens only (on a larger screen I would have a table with the label as the <code class=\"language-html\">&lt;th&gt;<\/code> element). So<\/p>\r\n<pre><code class=\"language-html\">&lt;style&gt;<\/code>\r\n<code class=\"language-css\">  .before-test:before { content: \"label: \"; }<\/code>\r\n<code class=\"language-html\">&lt;\/style&gt;<\/code><\/pre>\r\n<p>ought to work, right?<\/p>\r\n<p>No.<\/p>\r\n<p><code>:before<\/code>,despite its name, doesn't insert its content before the element specified. It inserts the content as the first child of the element specified. In other words, it works like jQuery's <a href=\"http:\/\/api.jquery.com\/prepend\/\"><code>prepend<\/code><\/a>, not like <a href=\"http:\/\/api.jquery.com\/before\/\"><code>before<\/code><\/a>. See Smashing Magazine's <a href=\"http:\/\/coding.smashingmagazine.com\/2011\/07\/13\/learning-to-use-the-before-and-after-pseudo-elements-in-css\/\">article<\/a> for more details.<\/p>\r\n<p>So the correct way to do this is:<p>\r\n<pre><code class=\"language-html demo\">&lt;div class=\"before-test\"&gt;&lt;input\/&gt;&lt;\/div&gt;<\/code><\/pre>\r\n<p>With the selector targeting the <em>enclosing<\/em> element.<\/p>\r\n<!--more-->\r\n<h2>Why bother:<\/h3>\r\n<p>Trying to make an order form <a href=\"http:\/\/www.alistapart.com\/articles\/responsive-web-design\/\">responsive<\/a>. It looks basically like this:<\/p>\r\n<pre><code class=\"language-html demo\">&lt;form id=exampleform&gt;\r\n  &lt;label&gt;Your Name: &lt;input \/&gt;&lt;\/label&gt;\r\n  &lt;table&gt;\r\n    &lt;thead&gt;\r\n      &lt;tr&gt;&lt;th&gt;Item&lt;\/th&gt;&lt;th&gt;Quantity&lt;\/th&gt;&lt;\/tr&gt;\r\n    &lt;\/thead&gt;\r\n    &lt;tbody&gt;\r\n      &lt;tr&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n      &lt;tr&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n      &lt;tr&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n      &lt;tr&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n      &lt;tr&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;td&gt;&lt;input\/&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n    &lt;\/tbody&gt;\r\n  &lt;\/table&gt;\r\n  &lt;input type=button value=\"Enter Order\" \/&gt;\r\n&lt;\/form&gt;<\/code><\/pre>\r\n<p>Which is all well and good, and an <a href=\"http:\/\/www.noupe.com\/how-tos\/better-ui-design-proper-use-of-tables.html\">appropriate use of a <code>&lt;table&gt;<\/code><\/a>. But when the window shrinks (or we're looking at a small screen) the table overflows horizontally. We don't want to have to scroll horizontally! So we can use a media query to change the table to a bunch of vertically oriented blocks when appropriate:<\/p>\r\n<pre><code class=\"language-css\">@media (max-width: 480px) {\r\n  form tr, form th, form td { display: block; }\r\n}<\/code><\/pre>\r\n<input type=button value=\"Toggle Table Flow\" id=button1 \/>\r\n<script>$('#button1').toggle(\r\n  function(){\r\n    $('tr, td, th', '#exampleform').css('display', 'block');\r\n  },function(){\r\n    $('tr', '#exampleform').css('display', 'table-row');\r\n    $('td, th', '#exampleform').css('display', 'table-cell');\r\n  }\r\n);\r\n<\/script>\r\n<p>But now, the table headers don't correspond to the input elements. So we need to label them. I'd like to use CSS rather than Javascript, so everything remains fluid without having to track window resizing events. So I just use Javascript to add the appropriate header as a <<a href=\"http:\/\/www.ejohn.org\/blog\/html-5-data-attributes\/\">code>data-<\/code><\/a> attribute, and display that:<\/p>\r\n<pre><code class=\"language-javascript demo\">$('#exampleform tr').each(function(){\r\n  $('td',this).each(function(i){\r\n    this.setAttribute(\"data-label\",$('th', '#exampleform').eq(i).text()+': ');\r\n  });\r\n});\r\n<\/code><\/pre>\r\n<p>And we use CSS to display it (I also hide the now-useless header with <code>clip<\/code>, the way WordPress does, so it's not hidden from screen readers):<\/p>\r\n\r\n<input type=button value=\"Toggle Label\" id=button2 \/>\r\n<script>$('#button2').click(function(){\r\n    $('#exampleform').toggleClass('labeled');\r\n});\r\n<\/script>\r\n<pre><code class=\"language-css\">form td:before { content: attr(data-label); }\r\nform thead { position: absolute !important; clip: rect(1px, 1px, 1px, 1px); }<\/code><\/pre>\r\n<p>And thus <code>:before<\/code> and <code>content: attr<\/code> come to the rescue.<\/p>","protected":false},"excerpt":{"rendered":"I wanted to use the CSS pseudoelement :before for manipulating input elements. I had &lt;input class=\"before-test\"\/&gt;, and I wanted to use CSS to add a label before the element on small screens only (on a larger screen I would have a table with the label as the &lt;th&gt; element). So &lt;style&gt; .before-test:before { content: \"label: [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2479"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=2479"}],"version-history":[{"count":38,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2479\/revisions"}],"predecessor-version":[{"id":2518,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2479\/revisions\/2518"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=2479"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=2479"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=2479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}