an

Cobalt–carbon/silica nanocomposites prepared by pyrolysis of a cobalt 2,2'-bipyridine terephthalate complex for remediation of cationic dyes

RSC Adv., 2020, 10,17660-17672
DOI: 10.1039/D0RA02752A, Paper
Open Access
Nusaybah Alotaibi, Hassan H. Hammud, Ranjith Kumar Karnati, Syed Ghazanfar Hussain, Javed Mazher, Thirumurugan Prakasam
A cobalt–carbon@silica nanocomposite was synthesized from a cobalt 2,2'-bipyridine terephthalate complex and its adsorption behavior towards crystal violet dye was tested using batch and column techniques.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Ultrathin δ-MnO2 nanoflakes with Na+ intercalation as a high-capacity cathode for aqueous zinc-ion batteries

RSC Adv., 2020, 10,17702-17712
DOI: 10.1039/D0RA02556A, Paper
Open Access
Haijun Peng, Huiqing Fan, Chenhui Yang, Yapeng Tian, Chao Wang, Jianan Sui
Sodium-ion intercalated δ-MnO2 nanoflakes are applied in an aqueous rechargeable zinc battery cathode with high energy density and excellent durable stability.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

A facile method for preparing Yb3+-doped perovskite nanocrystals with ultra-stable near-infrared light emission

RSC Adv., 2020, 10,17635-17641
DOI: 10.1039/D0RA01897J, Paper
Open Access
Chunqian Zhang, Aidi Zhang, Taoran Liu, Lin Zhou, Jun Zheng, Yuhua Zuo, Yongqi He, Juhao Li
A facile method for fabricating CsPbBr3:Yb3+@SiO2 NCs which guarantees high PLQY and excellent stability at the same time.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Dip-coating decoration of Ag2O nanoparticles on SnO2 nanowires for high-performance H2S gas sensors

RSC Adv., 2020, 10,17713-17723
DOI: 10.1039/D0RA02266G, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Tran Thi Ngoc Hoa, Nguyen Van Duy, Chu Manh Hung, Nguyen Van Hieu, Ho Huu Hau, Nguyen Duc Hoa
Ag2O nanoparticles decorated on the surface of on-chip growth SnO2 nanowires by a dip-coating method possessed excellent sensing performance for H2S gas.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Effect of temperature and large guest molecules on the C–H symmetric stretching vibrational frequencies of methane in structure H and I clathrate hydrates

RSC Adv., 2020, 10,17473-17478
DOI: 10.1039/D0RA02748K, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Go Fuseya, Satoshi Takeya, Akihiro Hachikubo
Temperature effect on C–H symmetric stretching frequencies of CH4 in water cages of sI and sH clathrate hydrates were clarified.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

One-pot oxime ligation from peptides bearing thiazolidine and aminooxyacetyl groups

RSC Adv., 2020, 10,17681-17685
DOI: 10.1039/D0RA03235B, Paper
Open Access
Stéphane Duflocq, Jingjing Zhou, Florent Huguenot, Michel Vidal, Wang-Qing Liu
Pd(II), acidic hydrolysis and iodine lead to one-pot oxime ligation from peptides bearing thiazolidine and aminooxyacetyl groups.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Position-locking of volatile reaction products by atmosphere and capping layers slows down photodecomposition of methylammonium lead triiodide perovskite

RSC Adv., 2020, 10,17534-17542
DOI: 10.1039/D0RA03572F, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Fengshuo Zu, Thorsten Schultz, Christian M. Wolff, Dongguen Shin, Lennart Frohloff, Dieter Neher, Patrick Amsalem, Norbert Koch
Gas pressure and capping layers under ultrahigh vacuum prevent methylammonium lead triiodide photo-degradation due to efficient back-reaction of volatile compounds.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

The synergistic influence of polyethyleneimine-grafted graphene oxide and iodide for the protection of steel in acidizing conditions

RSC Adv., 2020, 10,17739-17751
DOI: 10.1039/D0RA00864H, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
K. R. Ansari, Dheeraj Singh Chauhan, M. A. Quraishi, A. Y. Adesina, Tawfik A. Saleh
Herein, graphene oxide (GO) was chemically functionalized with polyethyleneimine (PEI) in a single step to obtain PEI-GO, which was characterized via FTIR spectroscopy, SEM, and TEM.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Boosting performances of triboelectric nanogenerators by optimizing dielectric properties and thickness of electrification layer

RSC Adv., 2020, 10,17752-17759
DOI: 10.1039/D0RA02181D, Paper
Open Access
Xiaofang Kang, Chongxiang Pan, Yanghui Chen, Xiong Pu
Enhanced output performances of a triboelectric nanogenerator (TENG) are achieved by optimizing the high-dielectric-constant filler content in the electrification layer and decreasing its thickness.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Mechanochemical approach to synthesize citric acid-soluble fertilizer of dittmarite (NH4MgPO4·H2O) from talc/NH4H2PO4 mixture

RSC Adv., 2020, 10,17686-17693
DOI: 10.1039/D0RA00387E, Paper
Open Access
Yonghao Tan, Lin Sha, Nengkui Yu, Zhengshuo Yang, Jun Qu, Zhigao Xu
Dittmarite synthesis by a mechanochemical route for application as a citric acid-soluble fertilizer.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Europium oxide nanorod-reduced graphene oxide nanocomposites towards supercapacitors

RSC Adv., 2020, 10,17543-17551
DOI: 10.1039/C9RA11012G, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Parisa Aryanrad, Hamid Reza Naderi, Elmira Kohan, Mohammad Reza Ganjali, Masoud Baghernejad, Amin Shiralizadeh Dezfuli
Fast charge/discharge cycles are necessary for supercapacitors applied in vehicles including, buses, cars and elevators.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Enhancing the performance of LARP-synthesized CsPbBr3 nanocrystal LEDs by employing a dual hole injection layer

RSC Adv., 2020, 10,17653-17659
DOI: 10.1039/D0RA02622K, Paper
Open Access
Dingyan Xu, Qun Wan, Siyao Wu, Yu Zhao, Xinglei Xu, Liang Li, Gufeng He
The current and power efficiencies of CsPbBr3 NC LEDs are improved 1.5 and 1.8 times by employing a dual HAT-CN/MoO3 hole injection layer.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

A highly sensitive, selective and renewable carbon paste electrode based on a unique acyclic diamide ionophore for the potentiometric determination of lead ions in polluted water samples

RSC Adv., 2020, 10,17552-17560
DOI: 10.1039/D0RA01435D, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
M. A. Zayed, Walaa H. Mahmoud, Ashraf A. Abbas, Aya E. Ali, Gehad G. Mohamed
Due to the toxicity of lead(II) to all living organisms destroying the central nervous system and leading to circulatory system and brain disorders, the development of effective and selective lead(II) ionophores for its detection is very important.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Selective cytotoxic effect against the MDA-MB-468 breast cancer cell line of the antibacterial palindromic peptide derived from bovine lactoferricin

RSC Adv., 2020, 10,17593-17601
DOI: 10.1039/D0RA02688C, Paper
Open Access
Andrea Barragán-Cárdenas, Maribel Urrea-Pelayo, Víctor Alfonso Niño-Ramírez, Adriana Umaña-Pérez, Jean Paul Vernot, Claudia Marcela Parra-Giraldo, Ricardo Fierro-Medina, Zuly Rivera-Monroy, Javier García-Castañeda
The cytotoxic effect against the breast cancer cell line MDA-MB-468 of the palindromic peptide LfcinB (21–25)Pal: 1RWQWRWQWR9 and its analogous peptides, obtained via alanine scanning, was evaluated.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Correction: Influence of co-cultures of Streptococcus thermophilus and probiotic lactobacilli on quality and antioxidant capacity parameters of lactose-free fermented dairy beverages containing Syzygium cumini (L.) Skeels pulp

RSC Adv., 2020, 10,16905-16905
DOI: 10.1039/D0RA90046J, Correction
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Sabrina Laís Alves Garcia, Gabriel Monteiro da Silva, Juliana Maria Svendsen Medeiros, Anna Paula Rocha de Queiroga, Blenda Brito de Queiroz, Daniely Rayane Bezerra de Farias, Joyceana Oliveira Correia, Eliane Rolim Florentino, Flávia Carolina Alonso Buriti
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Preparation of phosphorus-doped porous carbon for high performance supercapacitors by one-step carbonization

RSC Adv., 2020, 10,17768-17776
DOI: 10.1039/D0RA02398A, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Guanfeng Lin, Qiong Wang, Xuan Yang, Zhenghan Cai, Yongzhi Xiong, Biao Huang
P-doped porous carbon can be prepared by one-step carbonization using biomass sawdust impregnated with a small amount of phosphoric acid.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

A chitosan-based edible film with clove essential oil and nisin for improving the quality and shelf life of pork patties in cold storage

RSC Adv., 2020, 10,17777-17786
DOI: 10.1039/D0RA02986F, Paper
Open Access
Karthikeyan Venkatachalam, Somwang Lekjing
This study assessed chitosan (CS)-based edible films with clove essential oil (CO) and nisin (NI) singly or in combination, for improving quality and shelf life of pork patties stored in cold conditions.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Dependence on co-adsorbed water in the reforming reaction of ethanol on a Rh(111) surface

RSC Adv., 2020, 10,17787-17794
DOI: 10.1039/D0RA02015J, Paper
Open Access
Yu-Yao Hsia, Po-Cheng Chien, Lu-Hsin Lee, Yu-Ling Lai, Li-Chung Yu, Yao-Jane Hsu, Jeng-Han Wang, Meng-Fan Luo
Adsorbed ethanol molecules penetrated readily through pre-adsorbed water to react at the Rh surface; they decomposed at a promoted probability.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Effect of Zn doping on phase transition and electronic structures of Heusler-type Pd2Cr-based alloys: from normal to all-d-metal Heusler

RSC Adv., 2020, 10,17829-17835
DOI: 10.1039/D0RA02951C, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Xiaotian Wang, Mengxin Wu, Tie Yang, Rabah Khenata
By first-principles calculations, for Heusler alloys Pd2CrZ (Z = Al, Ga, In, Tl, Si, Sn, P, As, Sb, Bi, Se, Te, Zn), the effect of Zn doping on their phase transition and electronic structure has been studied in this work.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Microwave roasting of blast furnace slag for carbon dioxide mineralization and energy analysis

RSC Adv., 2020, 10,17836-17844
DOI: 10.1039/D0RA02846K, Paper
Open Access
Zike Han, Jianqiu Gao, Xizhi Yuan, Yanjun Zhong, Xiaodong Ma, Zhiyuan Chen, Dongmei Luo, Ye Wang
This paper highlights the potential of microwave roasting in solid-waste treatment and carbon dioxide storage.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Enhanced methane gas storage in the form of hydrates: role of the confined water molecules in silica powders

RSC Adv., 2020, 10,17795-17804
DOI: 10.1039/D0RA01754J, Paper
Open Access
Pinnelli S. R. Prasad, Burla Sai Kiran, Kandadai Sowjanya
Rapid and efficient methane hydrate conversions by utilising the water molecules confined in intra- and inter-granular space of silica powders.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Synthesis, characterization and corrosion inhibition behavior of 2-aminofluorene bis-Schiff bases in circulating cooling water

RSC Adv., 2020, 10,17816-17828
DOI: 10.1039/D0RA01903H, Paper
Open Access
Wenchang Wei, Zheng Liu, Chuxin Liang, Guo-Cheng Han, Jiaxing Han, Shufen Zhang
Two new bis-Schiff bases, namely 2-bromoisophthalaldehyde-2-aminofluorene (M1) and glutaraldehyde 2-aminofluorene (M2) were synthesized and were characterized, the potentiodynamic polarization curve confirmed that they were anode type inhibitors.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Correction: Narrowing band gap and enhanced visible-light absorption of metal-doped non-toxic CsSnCl3 metal halides for potential optoelectronic applications

RSC Adv., 2020, 10,17869-17869
DOI: 10.1039/D0RA90054K, Correction
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Jakiul Islam, A. K. M. Akther Hossain
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Effect of new carbonyl cyanide aromatic hydrazones on biofilm inhibition against methicillin resistant Staphylococcus aureus

RSC Adv., 2020, 10,17854-17861
DOI: 10.1039/D0RA03124K, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Xueer Lu, Ziwen Zhang, Yingying Xu, Jun Lu, Wenjian Tang, Jing Zhang
2e and 2j with strong p-NO2 and p-CF3 at phenyl ring had the lowest MICs against S. aureus and MRSA. 2e displayed unaided or synergistic efficacy against MRSA, especially combined with ofloxacin. EM revealed that 2e destroys biofilms and cell membranes.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Research on the controllable degradation of N-methylamido and dialkylamino substituted at the 5th position of the benzene ring in chlorsulfuron in acidic soil

RSC Adv., 2020, 10,17870-17880
DOI: 10.1039/D0RA00811G, Paper
Open Access
Fan-Fei Meng, Lei Wu, Yu-Cheng Gu, Sha Zhou, Yong-Hong Li, Ming-Gui Chen, Shaa Zhou, Yang-Yang Zhao, Yi Ma, Zheng-Ming Li
These results will provide valuable information to discover tailored SU with controllable degradation properties to meet the needs of individual crops.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Nitrogen-doped RuS2 nanoparticles containing in situ reduced Ru as an efficient electrocatalyst for hydrogen evolution

RSC Adv., 2020, 10,17862-17868
DOI: 10.1039/D0RA02530E, Paper
Open Access
Yan Xu, Xiaoping Gao, Jingyan Zhang, Daqiang Gao
The reasonable design that N-doping and in situ reduced Ru metal enhances the performance of N-RuS2/Ru for HER.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Selenium modulates cadmium-induced ultrastructural and metabolic changes in cucumber seedlings

RSC Adv., 2020, 10,17892-17905
DOI: 10.1039/D0RA02866E, Paper
Open Access
Hongyan Sun, Xiaoyun Wang, Huimin Li, Jiahui Bi, Jia Yu, Xianjun Liu, Huanxin Zhou, Zhijiang Rong
Intensive insight into the potential mechanisms of Se-induced Cd tolerance in cucumber seedlings is essential for further improvement of vegetable crop cultivation and breeding to obtain high yields and quality in Cd-contaminated soil.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Synthesis of heteroatom-containing pyrrolidine derivatives based on Ti(O-iPr)4 and EtMgBr-catalyzed carbocyclization of allylpropargyl amines with Et2Zn

RSC Adv., 2020, 10,17881-17891
DOI: 10.1039/D0RA02677H, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Rita N. Kadikova, Ilfir R. Ramazanov, Azat M. Gabdullin, Oleg S. Mozgovoj, Usein M. Dzhemilev
The Ti(O-iPr)4 and EtMgBr-catalyzed regio and stereoselective carbocyclization of N-allyl-substituted 2-alkynylamines with Et2Zn, followed by deuterolysis or hydrolysis, affords the corresponding methylenepyrrolidine derivatives in high yields.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Nanoporous materials with predicted zeolite topologies

RSC Adv., 2020, 10,17760-17767
DOI: 10.1039/D0RA01888K, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Vladislav A. Blatov, Olga A. Blatova, Frits Daeyaert, Michael W. Deem
Topological exploration of crystal structures demonstrates the presence of known zeolites, inorganics, and MOFs in a database of predicted materials.
The content of this RSS Feed (c) The Royal Society of Chemistry




an

Anatomy of an HTML5 WordPress theme

This site has been written in HTML5 and used to use WordPress to manage the content. I’ll explain why I used HTML5, describe the structure of the theme templates, and show some of the ways I tried to tame WordPress’s tendency to add mess to the source code.

As this is my personal site I wanted to experiment with using HTML5, CSS3, and WAI-ARIA. All these documents are currently working drafts and subject to change. However, the web documents and applications of the future are going to be written in HTML5 and I wanted to see the benefits of using it to markup static documents. Using CSS 2.1, let alone the CSS3 selectors and properties that some browser vendors have implemented, has many advantages for controlling the presentation of semantically coded documents. For this reason I am not going to avoid using basic CSS 2.1 selectors just to faithfully reproducing this site’s design in IE6. However, I have tried to accommodate IE 7 and IE 8 users by using an HTML5 enabling script so that the new HTML5 elements can be styled in those browsers if users have Javascript enabled.

HTML5 templates

I started with a static prototype of this site developed on my local server. WordPress makes it very easy to create your own templates and, therefore, it is no problem to use HTML5. This theme only has 3 main templates: index, single, and archive. There are of course templates for 404s, attachments, comments, etc., but I won’t discuss them as they are all based on the 3 main templates. All the templates include ARIA roles as an accessibility aide.

The single.php template has this rough structure:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <link rel="stylesheet" href="default.css">
</head>

<body>
  <header role="banner"></header>
  <nav role="navigation"></nav>
  <article role="main">
    <header>
      <time datetime="YYYY-MM-DD"></time>
      <h1></h1>
    </header>
    <footer></footer>
  </article>
  <nav></nav>
  <aside role="complementary"></aside>
  <footer role="contentinfo">
    <small></small>
  </footer>
</body>
</html>

The first line of the document is the HTML5 DOCTYPE. The new <article> element contains the content of each post. The same structure is used for the index.php template except that there are several articles displayed on each page and the ARIA role value of main is not used. In contrast, the archive.php template houses all the article excerpts in a <section> element with the ARIA role of main because the list of archived posts is itself the main content of the document.

A clean theme

WordPress tends to add classes, elements, and other bits of code in certain places. I haven’t used any of the WordPress functions that add class names to the body and to elements wrapping a post and also wanted to avoid cluttering the source code with any other unnecessary markup. This required a bit of fiddling around with the theme’s functions.php file. I’m not a PHP developer so this might not be pretty!

Removing actions from wp_head()

WordPress has a hook called wp_head that sits in the header.php of most themes. To avoid it inserting unwanted code into the <head> of the document I used the remove_action function to disable the functions that were responsible. The following code was added to the functions.php file of my theme:

// Remove links to the extra feeds (e.g. category feeds)
remove_action( 'wp_head', 'feed_links_extra', 3 );
// Remove links to the general feeds (e.g. posts and comments)
remove_action( 'wp_head', 'feed_links', 2 );
// Remove link to the RSD service endpoint, EditURI link
remove_action( 'wp_head', 'rsd_link' );
// Remove link to the Windows Live Writer manifest file
remove_action( 'wp_head', 'wlwmanifest_link' );
// Remove index link
remove_action( 'wp_head', 'index_rel_link' );
// Remove prev link
remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 );
// Remove start link
remove_action( 'wp_head', 'start_post_rel_link', 10, 0 );
// Display relational links for adjacent posts
remove_action( 'wp_head', 'adjacent_posts_rel_link', 10, 0 );
// Remove XHTML generator showing WP version
remove_action( 'wp_head', 'wp_generator' );

Source: WPEngineer.com: Cleanup WordPress Header

Removing an empty <span>

If you want to create excerpts you can either write them into the excerpt box or use the <--more--> quicktag in the WordPress editor. I just wanted the first paragraph of my posts to be used as the excerpt and so using the in-editor tag was the most practical approach I was aware of. However, when you do this WordPress will insert an empty <span> in the post’s content. This element has an id so that the area following the excerpt can be targeted by “more” or “continue reading” links. I removed both the empty <span> and the jump link by adding the following code to the functions.php file of the theme:

// removes empty span
function remove_empty_read_more_span($content) {
  return eregi_replace("(<p><span id="more-[0-9]{1,}"></span></p>)", "", $content);
}
add_filter('the_content', 'remove_empty_read_more_span');

Source: Ganda Manurung: Remove Empty Span Tag On WordPress

// removes url hash to avoid the jump link
function remove_more_jump_link($link) {
  $offset = strpos($link, '#more-');
  if ($offset) {
    $end = strpos($link, '"',$offset);
  }
  if ($end) {
    $link = substr_replace($link, '', $offset, $end-$offset);
  }
  return $link;
}
add_filter('the_content_more_link', 'remove_more_jump_link');

Source: WordPress Codex: Customizing the Read More

Displaying images in the excerpt

For posts that display nothing but a photograph (yes, they will be shit but I’m hoping it gets me using my camera a bit more often) I wanted the image to show up in the archives. Equally, if the first paragraph of a post contained a link I wanted that to be preserved. The default the_excerpt() template tag doesn’t allow for this so it needed some modifying. I added a new function, which is just a modified version of the core excerpt function, to the functions.php file and then made sure that the template tag executed this function rather than the one contained in the core WordPress files.

function improved_trim_excerpt($text) {
   if ( '' == $text ) {
      $text = get_the_content('');
      $text = strip_shortcodes( $text );
      $text = apply_filters('the_content', $text);
      $text = str_replace(']]>', ']]&amp;gt;', $text);
      $text = strip_tags($text, '<p><img><a>');
      $excerpt_length = apply_filters('excerpt_length', 55);
      $words = explode(' ', $text, $excerpt_length + 1);
      if (count($words) > $excerpt_length) {
         array_pop($words);
         array_push($words, '[...]');
         $text = implode(' ', $words);
         $text = force_balance_tags($text);
      }
   }
   return $text;
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'improved_trim_excerpt');

Source: Aaron Russell: Improving WordPress’ the_excerpt() template tag

I prefer not to have empty elements in the markup and so I needed a way to conditionally insert the “Older entries”, “Newer Entries”, etc., links into templates. The solution I’m using here, which isn’t perfect, is to add this to functions.php:

function show_posts_nav() {
  global $wp_query;
  return ($wp_query->max_num_pages > 1);
}

Source: Eric Martin: Conditional navigation links in WordPress

And then to wrap the navigation markup in the templates with the following:

<?php if (show_posts_nav()) : ?>
<nav>
   <ul>
      <li><?php next_posts_link('&#171; Older Entries') ?></li>
      <li><?php previous_posts_link('Newer Entries &#187;') ?></li>
   </ul>
</nav>
<?php endif; ?>

Summary

It’s fairly easy to create a simple site with HTML5 and to use WordPress to deliver it. At the moment there are issues with Internet Explorer because you cannot style HTML5 elements unless you use Javascript. However, HTML5 redefines the meaning of certain elements (such as <dl>, which has become a more versatile “description list”) and allows block elements to be wrapped in a link. Therefore, there is still benefit in using the HTML5 DOCTYPE even if you do not make use of the new elements.

Further reading

  1. HTML5 working draft
  2. HTML5 differences from HTML4
  3. Accessible Rich Internet Applications (WAI-ARIA) 1.0




an

Multiple Backgrounds and Borders with CSS 2.1

Using CSS 2.1 pseudo-elements to provide up to 3 background canvases, 2 fixed-size presentational images, and multiple complex borders for a single HTML element. This method of progressive enhancement works for all browsers that support CSS 2.1 pseudo-elements and their positioning. No CSS3 support required.

Support: Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10+, IE8+.

How does it work?

Essentially, you create pseudo-elements using CSS (:before and :after) and treat them similarly to how you would treat HTML elements nested within your target element. But they have distinct benefits – beyond semantics – over the use of nested HTML elements.

To provide multiple backgrounds and/or borders, the pseudo-elements are pushed behind the content layer and pinned to the desired points of the HTML element using absolute positioning.

The pseudo-elements contain no true content and are absolutely positioned. This means that they can be stretched to sit over any area of the “parent” element without affecting its content. This can be done using any combination of values for the top, right, bottom, left, width, and height properties and is the key to their flexibility.

What effects can be achieved?

Using just one element you can create parallax effects, multiple background colours, multiple background images, clipped background images, image replacement, expandable boxes using images for borders, fluid faux columns, images existing outside the box, the appearance of multiple borders, and other popular effects that usually require images and/or the use of presentational HTML. It is also possible to include 2 extra presentational images as generated content.

The Multiple Backgrounds with CSS 2.1 and Multiple Borders with CSS 2.1 demo pages show how several popular examples of these effects can be achieved with this technique.

Most structural elements will contain child elements. Therefore, more often than not, you will be able to gain a further 2 pseudo-elements to use in the presentation by generating them from the first child (and even last-child) element of the parent element. In addition, you can use style changes on :hover to produce complex interaction effects.

Example code: multiple background images

Using this technique it is possible to reproduce multiple-background parallax effects like those found on the Silverback site using just one HTML element.

The element gets its own background image and any desired padding. By relatively positioning the element it acts as the reference point when absolutely positioning the pseudo-elements. The positive z-index will allow for the correct z-axis positioning of the pseudo-elements.

#silverback {
  position: relative;
  z-index: 1;
  min-width: 200px;
  min-height: 200px;
  padding: 120px 200px 50px;
  background: #d3ff99 url(vines-back.png) -10% 0 repeat-x;
}

Both pseudo-elements are absolutely positioned and pinned to each side of the element. The z-index value of -1 moves the pseudo-elements behind the content layer. This way the pseudo-elements sit on top of the element’s background and border but all the content is still selectable or clickable.

#silverback:before,
#silverback:after {
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  padding-top: 100px;
}

Each pseudo-element then has a repeated background-image set. This is all that is needed to reproduce the parallax effect.

The content property lets you add an image as generated content. With two pseudo-elements you can add 2 further images to an element. They can be crudely positioned within the pseudo-element box by varying other properties such as text-align and padding.

#silverback:before {
  content: url(gorilla-1.png);
  padding-left: 3%;
  text-align: left;
  background: transparent url(vines-mid.png) 300% 0 repeat-x;
}

#silverback:after {
  content: url(gorilla-2.png);
  padding-right: 3%;
  text-align: right;
  background: transparent url(vines-front.png) 70% 0 repeat-x;
}

The finished product is part of the Multiple Backgrounds with CSS 2.1 demo.

Example code: fluid faux columns

Another application is creating equal height fluid columns without images or extra nested containers.

The HTML base is very simple. I’ve used specific classes on each child div rather than relying on CSS 2.1 selectors that IE6 does not support. If you don’t require IE6 support you don’t actually need the classes.

<div id="faux">
  <div class="main">[content]</div>
  <div class="supp1">[content]</div>
  <div class="supp2">[content]</div>
</div>

The percentage-width container is once again relatively positioned and a positive z-index is set. Applying overflow:hidden gets the element to wrap its floated children and will hide the overflowing pseudo-elements. The background colour will provide the colour for one of the columns.

#faux {
  position: relative;
  z-index: 1;
  width: 80%;
  margin: 0 auto;
  overflow: hidden;
  background: #ffaf00;
}

By using relative positioning on the child div‘s you can also control the order of the columns independently of their source order.

#faux div {
  position: relative;
  float: left;
  width: 30%;
}

#faux .main { left: 35%; }
#faux .supp1 { left: -28.5%; }
#faux .supp2 { left: 8.5%; }

The other two full-height columns are produced by creating, sizing, and positioning pseudo-elements with backgrounds. These backgrounds can be (repeating) images if the design requires.

#faux:before,
#faux:after {
   content: "";
   position: absolute;
   z-index: -1;
   top: 0;
   right: 0;
   bottom: 0;
   left: 33.333%;
   background: #f9b6ff;
}

#faux:after {
   left: 66.667%;
   background: #79daff;
}

The finished product is part of the Multiple Backgrounds with CSS 2.1 demo.

Example code: multiple borders

Multiple borders are produced in much the same way. Using them can avoid the need for images to produce simple effects.

An element must be relatively positioned and have sufficient padding to contain the width of the extra border you will be creating with pseudo-elements.

#borders {
   position: relative;
   z-index: 1;
   padding: 30px;
   border: 5px solid #f00;
   background: #ff9600;
}

The pseudo-elements are positioned at specific distances away from the edge of the element’s box, moved behind the content layer with the negative z-index, and given the border and background values you want.

#borders:before {
   content: "";
   position: absolute;
   z-index: -1;
   top: 5px;
   left: 5px;
   right: 5px;
   bottom: 5px;
   border: 5px solid #ffea00;
   background: #4aa929;
}

#borders:after {
   content: "";
   position: absolute;
   z-index: -1;
   top: 15px;
   left: 15px;
   right: 15px;
   bottom: 15px;
   border: 5px solid #00b4ff;
   background: #fff;
}

That’s all there is to it. The finished product is part of the Multiple Borders with CSS 2.1 demo.

Progressive enhancement and legacy browsers

IE6 and IE7 have no support for CSS 2.1 pseudo-elements and will ignore all :before and :after declarations. They get none of the enhancements but are left with the basic usable experience.

A warning about Firefox 3.0

Firefox 3.0 supports CSS 2.1 pseudo-elements but does not support their positioning. Due to this partial support, you should avoid declaring display:block for absolutely positioned pseudo-elements that explicitly declare a width or height values. However, when using borders there is no graceful fallback for Firefox 3.0. Although, sometimes an improved appearance in Firefox 3.0 can be achieved by adding display:block to pseudo-element hacks that use borders.

Enhancing with CSS3

All the applications included in this article could be further enhanced to take advantage of present-day CSS3 implementations.

Using border-radius, rgba, and transforms, and CSS3 multiple background images in tandem with pseudo-elements can produce even more complex presentations that I hope to include in a future article. Currently there is no browser support for the use of CSS3 transitions or animations on pseudo-elements.

In the future: CSS3 pseudo-elements

The proposed extensions to pseudo-elements in the CSS3 Generated and Replaced Content Module include the addition of nested pseudo-elements (::before::before), multiple pseudo-elements (::after(2)), wrapping pseudo-elements (::outside), and the ability to insert pseudo-elements into later parts of the document (::alternate).

These changes would provide a near limitless number, and arrangement, of pseudo-elements for all sorts of complex effects and presentations using just one element.

Let me know what you’ve done

I’ve focused on just a few applications and popular effects. If you find other applications, limitations, or want to share how you’ve applied this technique please leave a comment below or let me know on Twitter (@necolas.

Translations




an

Animal virtues & choice fetishism

The following is an interesting extract from Straw Dogs by John Gray (pp. 109–116) discussing some of the differences between Western and Taoist philosophical traditions.

The fetish of choice

For us, nothing is more important than to live as we choose. This is not because we value freedom more than people did in earlier times. It is because we have identified the good life with the chosen life.

For the pre-Socratic Greeks, the fact that our lives are framed by limits was what makes us human. Being born a mortal, in a given place and time, strong or weak, swift or slow, brave or cowardly, beautiful or ugly, suffering tragedy or being spared it – these features of our lives are given to us, they cannot be chosen. If the Greeks could have imagined a life without them, they could not have recognised it as that of a human being.

The ancient Greeks were right. The ideal of the chosen life does not square with how we live. We are not authors of our lives; we are not even part-authors of the events that mark us most deeply. Nearly everything that is most important in our lives is unchosen. The time and place we are born, our parents, the first language we speak – these are chance, not choice. It is the casual drift of things that shapes our most fateful relationships. The life of each of us is a chapter of accidents.

Personal autonomy is the work of our imagination, not the way we live. Yet we have been thrown into a time in which everything is provisional. New technologies alter our lives daily. The traditions of the past cannot be retrieved. At the same time we have little idea of what the future will bring. We are forced to live as if we were free.

The cult of choice reflects the fact that we must improvise our lives. That we cannot do otherwise is a mark of our unfreedom. Choice has become a fetish; but the mark of a fetish is that it is unchosen.

Animal virtues

The dominant Western view…teaches that humans are unlike other animals, which simply respond to the situations in which they find themselves. We can scrutinise our motives and impulses; we can know why we act as we do. By becoming ever more self-aware, we can approach a point at which our actions are the results of our choices. When we are fully conscious, everything we do will be done for reasons we can know. At that point, we will be authors of our lives.

This may seem fantastical, and so it is. Yet it is what we are taught by Socrates, Aristotle and Plato, Descartes, Spinoza and Marx. For all of them, consciousness is our very essence, and the good life means living as a fully conscious individual.

Western thought is fixated on the gap between what is and what ought to be. But in everyday life we do not scan our options beforehand, then enact the one that is best. We simply deal with whatever is at hand. …Different people follow different customs; but in acting without intention, we are not simply following habit. Intentionless acts occur in all sorts of situations, including those we have never come across before.

Outside the Western tradition, the Taoists of ancient China saw no gap between is and ought. Right action was whatever comes from a clear view of the situation. They did not follow moralists – in their day, Confucians – in wanting to fetter human beings with rules or principles. For Taoists, the good life is only the natural life lived skillfully. It has no particular purpose. It has nothing to do with the will, and it does not consist in trying to realise any ideal. Everything we do can be done more or less well; but if we act well it is not because we translate our intentions into deeds. It is because we deal skillfully with whatever needs to be done. The good life means living according to our natures and circumstances. There is nothing that says that it is bound to be the same for everybody, or that it must conform with ‘morality’.

In Taoist thought, the good life comes spontaneously; but spontaneity is far from simply acting on the impulses that occur to us. In Western traditions such as Romanticism, spontaneity is linked with subjectively. In Taoism it means acting dispassionately, on the basis of an objective view of the situation at hand. The common man cannot see things objectively, because his mind is clouded by anxiety about achieving his goals. Seeing clearly means not projecting our goals into the world; acting spontaneously means acting according to the needs of the situation. Western moralists will ask what is the purpose of such action, but for Taoists the good life has no purpose. It is like swimming in a whirlpool, responding to the currents as they come and go. ‘I enter with the inflow, and emerge with the outflow, follow the Way of the water, and do not impose my selfishness upon it. This is how I stay afloat in it,’ says the Chuang-Tzu.

In this view, ethics is simply a practical skill, like fishing or swimming. The core of ethics is not choice or conscious awareness, but the knack of knowing what to do. It is a skill that comes with practice and an empty mind. A.C. Graham explains:

The Taoist relaxes the body, calms the mind, loosens the grip of categories made habitual by naming, frees the current of thought for more fluid differentiations and assimilations, and instead of pondering choices lets the problems solve themselves as inclination spontaneously finds its own direction. …He does not have to make decisions based on standards of good and bad because, granted only that enlightenment is better than ignorance, it is self-evident that among spontaneous inclinations the one prevailing in the greatest clarity of mind, other things being equal, will be best, the one in accord with the Way.

Few humans beings have the knack of living well. Observing this, the Taoists looked to other animals as their guides to the good life. Animals in the wild know how to live, they do not need to think or choose. It is only when they are fettered by humans that they cease to live naturally.

As the Chuang-Tzu puts it, horses, when they live wild, eat grass and drink water; when they are content, they entwine their necks and rub each other. When angry, they turn their backs on each other and kick out. This is what horses know. But if harnessed together and lined up under constraints, they know how to look sideways and to arch their necks, to career around and try to spit out the bit and rid themselves of the reins.

For people in thrall to ‘morality’ , the good life means perpetual striving. For Taoists it means living effortlessly, according to our natures. The freest human being is not the one who acts on reasons he has chosen for himself, but one who never has to choose. Rather than agonising over alternatives, he responds effortlessly to situations as they arise. He lives not as he chooses but as he must. Such a human has the perfect freedom of a wild animal – or a machine. As the Lieh-Tzu says: ‘The highest man at rest is as though dead, in movement is like a machine. He knows neither why he is at rest nor why he is not, why he is in movement nor why he is not.’

The idea that freedom means becoming like a wild animal or machine is offensive to Western religious and humanist prejudices, but it is consistent with the most advanced scientific knowledge. A.C. Graham explains:

Taoism coincides with the scientific worldview at just those points where the latter most disturbs westerners rooted in the Christian tradition – the littleness of man in a vast universe; the inhuman Tao which all things follow, without purpose and indifferent to human needs; the transience of life, the impossibility of knowing what comes after death; unending change in which the possibility of progress is not even conceived; the relativity of values; a fatalism very close to determinism; even a suggestion that the human organism operates like a machine.

Autonomy means acting on reasons I have chosen; but the lesson of cognitive science is that there is no self to do the choosing. We are far more like machines and wild animals than we imagine. But we cannot attain the amoral selflessness of wild animals, or the choiceless automatism of machines. Perhaps we can learn to live more lightly, less burdened by morality. We cannot return to a purely spontaneous existence.




an

Yet another HTML5 fallback strategy for IE

If you’re using HTML5 elements then you’re probably also using a JavaScript shiv to help make it possible to style those elements in versions of Internet Explorer prior to IE9. But when JavaScript is disabled the accessibility of the content may be affected in these versions of IE. This is one way to provide a more accessible fallback.

The concept is to ensure that all modern browsers are served the default style sheet(s) and that people using older versions of IE only download them if JavaScript is enabled. When JavaScript is not enabled, people using those browsers can be served either no styles at all (as Yahoo! suggests for browsers receiving C-Grade support) or simple fallback styles.

Client-side method: conditional comments

Doing this on the client-side comes at the cost of having to litter your code with proprietary conditional comments. First, it’s necessary to comment out the default style sheet(s) from versions of IE earlier than IE9. All other browsers will be able to read the file(s).

<!--[if ! lt IE 9]><!-->
<link rel="stylesheet" href="/css/default.css">
<!--<![endif]-->

For earlier versions of IE, an HTML5 shiv is included and the necessary link elements are created and added to the DOM using JavaScript. This means that when JavaScript is not enabled in IE7 or IE8 the style sheet will not be present, resulting in an unstyled HTML page. In this example, IE6 won’t be served CSS at all.

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
   (function() {
      var link = document.createElement("link");
      link.rel = "stylesheet";
      link.href = "/css/default.css";
      document.getElementsByTagName("head")[0].appendChild(link);
   }());
</script>
<![endif]-->

To support multiple style sheets, an array and for loop can be used.

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
   (function() {
      var css = [
         '/css/default.css',
         '/css/section.css',
         '/css/custom.css'
      ];
      var i;
      var link = document.createElement('link');
      var head = document.getElementsByTagName('head')[0];
      var tmp;

      link.rel = 'stylesheet';

      for(i = 0; i < css.length; i++){
         tmp = link.cloneNode(true);
         tmp.href = css[i];
         head.appendChild(tmp);
      }
   }());
</script>
<![endif]-->

Thanks to Remy Sharp and Mathias Bynens for helping me to improve this script. Fork it.

Rather than serving unstyled content, it may be preferable to provide some simple fallback styles. This can be done by linking to a separate style sheet wrapped in noscript tags. In this example, IE6 will always use these legacy styles while IE7 and IE8 will do so only when JavaScript is disabled.

<!--[if lt IE 9]>
<noscript>
   <link rel="stylesheet" href="/css/legacy.css">
</noscript>
<![endif]-->

You may wish to use a generic style sheet, such as “Universal IE6 CSS”, or spend a few minutes crafting your own and ensuring that the typography and colours approximate those in the default style sheet.

The complete example code is as follows:

<!--[if ! lt IE 9]><!-->
<link rel="stylesheet" href="/css/default.css">
<!--<![endif]-->

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
   (function() {
      var link = document.createElement("link");
      link.rel = "stylesheet";
      link.href = "/css/default.css";
      document.getElementsByTagName("head")[0].appendChild(link);
   }());
</script>
<![endif]-->

<!--[if lt IE 9]>
<noscript>
   <link rel="stylesheet" href="/css/legacy.css">
</noscript>
<![endif]-->

Server-side method: user-agent string detection

The drawbacks of current client-side approaches to IE fallbacks is that they are IE-specific, make extensive use of conditional comments, and have to use JavaScript to create or rewrite link elements. This blog makes use of an alternative approach: server-side user-agent detection. It was inspired by Yahoo!’s Graded Browser Support strategy – created by Nate Koechley – which recommends that all CSS and JavaScript is withheld from legacy browsers (not limited to IE).

The source code in the head of this blog changes when viewed in modern browsers, IE8, and legacy browsers that are incapable of styling HTML5 elements (e.g. Firefox 2) or lack adequate CSS2.1 support (e.g. IE7).

Browsers are assumed to be capable; there is no need to update the script every time a new browser is released. Only when a browser is deemed to be severely incapable is it added to a “blacklist” and served simple styles to ensure that the accessibility of the content is maintained. This is the method I prefer, although it does require more time upfront.




an

Jump links and viewport positioning

Using within-page links presses the jumped-to content right at the very top of the viewport. This can be a problem when using a fixed header. With a bit of hackery, there are some CSS methods to insert space between the top of the viewport and the target element within a page.

Demo: Jump links and viewport positioning

Known support: varies depending on method used.

This experiment is the result of a post Chris Coyier made on Forrst. Chris’ method was to add an empty span element to the target element, shift the id attribute onto the span, and then absolutely position the span somewhere above it’s parent element.

That method works but it requires changes to the HTML. The comments on Chris’ post suggested the use of psuedo-elements or padding. This experiment expands on, and combines, some of those suggestions to show the limitations of each method and document their browser support.

Simplest method

If you need to jump to an element with simple styling then using the :before pseudo-element is a quick and simple approach.

#target:before {
   content: "";
   display: block;
   height: 50px;
   margin: -30px 0 0;
}

The drawbacks are that it requires browser support for pseudo-elements and it will fail if the target element has a background colour, a repeated background image, padding-top, or border-top as part of its rule set.

More robust method

The more robust method uses a transparent border, negative margin, and the background-clip property. If a top border is required then it can be mimicked using a pseudo-element, as described in Multiple Backgrounds and Borders with CSS 2.1.

#target {
   position: relative;
   border-top: 52px solid transparent;
   margin: -30px 0 0;
   -webkit-background-clip: padding-box;
   -moz-background-clip: padding;
   background-clip: padding-box;
}

#target:before {
   content: "";
   position: absolute;
   top: -2px;
   left: 0;
   right: 0;
   border-top: 2px solid #ccc;
}

There are still drawbacks: it requires browser support for background-clip if there is a background color, gradient, or repeating image set on the target element; it requires browser support for pseudo-elements and their positioning if a top border is desired; and it interferes with the standard use of margins.

To see these methods in action – as well as more details on the code, browser support, and drawbacks – have a look at the demo page. Please let me know if you know of better techniques.




an

Quick tip: git-checkout specific files from another branch

The git-checkout command can be used to update specific files or directories in your working tree with those from another branch, without merging in the whole branch. This can be useful when working with several feature branches or using GitHub Pages to generate a static project site.

The git-checkout manual page describes how the git checkout command is not just useful for switching between branches.

When <paths> or --patch are given, git checkout does not switch branches. It updates the named paths in the working tree from the index file or from a named <tree-ish> (most often a commit)…The <tree-ish> argument can be used to specify a specific tree-ish (i.e. commit, tag or tree) to update the index for the given paths before updating the working tree.

In git, a tree-ish is a way of referring to a particular commit or tree. This can be a partial sha or the branch, remote, and tag name pointers.

The syntax for using git checkout to update the working tree with files from a tree-ish is as follows:

git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>…

Therefore, to update the working tree with files or directories from another branch, you can use the branch name pointer in the git checkout command.

git checkout <branch_name> -- <paths>

As an example, this is how you could update your gh-pages branch on GitHub (used to generate a static site for your project) to include the latest changes made to a file that is on the master branch.

# On branch master
git checkout gh-pages
git checkout master -- myplugin.js
git commit -m "Update myplugin.js from master"

The need to update my gh-pages branch with specific files from my master branch was how I first found out about the other uses of the checkout command. It’s worth having a read of the rest of the git-checkout manual page and experimenting with the options.




an

An introduction to CSS pseudo-element hacks

CSS is a versatile style language that is most frequently used to control the look and formatting of an HTML document based on information in the document tree. But there are some common publishing effects – such as formatting the first line of a paragraph – that would not be possible if you were only able to style elements based on this information. Fortunately, CSS has pseudo-elements and pseudo-classes.

As their names imply, they are not part of the DOM in the way that ‘real’ HTML elements and classes are. Instead, they are CSS abstractions that provide additional, and otherwise inaccessible, information about the document.

This article will discuss the CSS pseudo-elements that are part of CSS 2.1 – :first-letter, :first-line, :before, and :after – and how the :before and :after pseudo-elements can be exploited to create some interesting effects, without compromising the simplicity of your HTML. But first, let’s look at each type of pseudo-element and how to use them in their basic form.

The :first-line and :first-letter pseudo-elements

The :first-line pseudo-element lets you apply styles to the first formatted line of a block container element (i.e., elements with their display property set to block, inline-block, list-item, table-caption, or table-cell). For example:

p:first-line { font-weight: bold; }

…will change the first line of every paragraph to bold. The :first-line pseudo-element can be treated as if it were an extra HTML inline element wrapping only the first line of text in the paragraph.

The :first-letter pseudo-element lets you apply styles to the first letter (and any preceding punctuation) of the first formatted line of a block container element. No other inline content (e.g. an image) can appear before the text. For example:

p:first-letter { float: left; font-size: 200%; }

…will produce a basic ‘drop cap’ effect. The first letter of every paragraph will be floated left, and twice as large as the other letters in the paragraph. The :first-letter pseudo-element can be treated as if it were an extra HTML inline element wrapping only the first letter of text in the paragraph.

The :first-line and :first-letter pseudo-elements can only be attached to block container elements, but the first formatted line can be contained within any block-level descendant (e.g., elements with their display property set to block or list-item) in the same flow (i.e., not floated or positioned). For example, the following HTML fragment and CSS:

<div><p>An example of the first line of text being within a descendant element</p></div>

div:first-line { font-weight: bold; }

…would still result in a bold first line of text, because the paragraph’s text is the first formatted line of the div.

The :before and :after pseudo-elements

The :before and :after pseudo-elements are used to insert generated content before or after an element’s content. They can be treated as if they were extra HTML inline elements inserted just before and after the content of their associated element.

Generated content is specified using the content property which, in CSS 2.1, can only be used in conjunction with the :before and :after pseudo-elements. Furthermore, you must declare the content property in order to generate the :before and :after pseudo-elements.

The content property can take string, url(), attr(), counter() and counters() values. The url() value is used to insert an image. The attr() function returns as a string the value of the specified attribute for the associated element. The counter() and counters() functions can be used to display the value of any CSS counters.

For example, the following HTML fragment and CSS:

<a href="http://wikipedia.org">Wikipedia</a>

a:after { content: " (" attr(href) ")"; }

…would display the value of the href attribute after a link’s content, resulting in the following anchor text for the example above: Wikipedia (http://wikipedia.org). This can be a helpful way to display the destination of specific links in printed web documents.

Keep in mind that CSS is meant for adding presentation and not content. Therefore, the content property should be used with caution.

It’s also worth noting that the :first-letter and :first-line pseudo-elements apply to the first letter and first line of an element including any generated content inserted using the :before and :after pseudo-elements.

Browser support for pseudo-elements

The :first-letter and :first-line pseudo-elements were introduced in CSS1 and there is wide basic support for them. However, IE 6 and IE 7 have particularly buggy implementations; even modern browsers are not entirely consistent in the way that they handle the :first-line and :first-letter pseudo-elements (example bugs).

The :before and :after pseudo-elements were introduced in the CSS 2.1 specification and are fully implemented in Firefox 3.5+, IE 8+, Safari 3+, Google Chrome, and Opera. Modern versions of Firefox even support CSS transitions and animations applied to pseudo-elements. However, legacy browsers like IE 6 and IE 7 do not support the :before and :after pseudo-elements at all.

For more detailed information on pseudo-element browser support, browser bugs, and workarounds, have a look at Sitepoint’s reference and this article on IE 6/7 issues.

In most cases, the :before and :after pseudo-elements can be used as part of a ‘progressive enhancement’ approach to design and development, because IE 6 and IE 7 will simply ignore them altogether. Alternatively, Modernizr now includes a robust feature test for generated content, providing one way to specify fallbacks or enhancements depending on browser support. The important thing is to remember to check what happens in browsers where support is missing.

Alternative ways to use pseudo-elements

Let’s take a look at how the :before and :after pseudo-elements can be used as the basis for some interesting effects. Most of the time, this involves generating empty :before and :after pseudo-elements by declaring an empty string as the value of the content property. They can then be manipulated as if they were empty inline HTML elements, keeping your HTML clean and giving you full control of certain effects from within CSS style sheets.

Simple visual enhancements, like speech bubbles and folded corners, can even be created without the need for images. This relies on the fact that you can create simple shapes using CSS.

Several types of ‘CSS polygons’ can be created as a result of browsers rendering borders at an angle when they meet. This can be exploited to create triangles. For example, the following HTML fragment and CSS:

<div class="triangle"></div>

.triangle {
  width: 0;
  height: 0;
  border-width: 20px;
  border-style: solid;
  border-color: red transparent transparent;
}

…will create a downward pointing, red triangle. By varying the width, height, border-width, border-style, and border-color values you can produce different shapes and control their orientation and colour. For more information, be sure to read Jon Rogan’s summary of the technique.

The more advanced pseudo-element hacks use the extra background canvas afforded by each :before and :after pseudo-element. This can help you crop background images, control the opacity of background images, and ‘fake’ multiple backgrounds and borders in browsers without support for CSS3 multiple backgrounds (e.g., IE 8). Taken to ludicrous extremes, you can even build a whole CSS icon set. To start with, let’s look at some simple effects that can be created without images or presentational HTML.

Creating CSS speech bubbles

In this example, a quote is styled to look like a speech bubble, using CSS. This is done by creating a triangle using a pseudo-element, and then absolutely positioning it in the desired place. By adding position:relative to the CSS styles for the HTML element, you can absolutely position the :after pseudo-element relative to its associated element.

<div class="quote">[Quoted text]</div>

.quote {
  position: relative;
  width: 300px;
  padding: 15px 25px 20px;
  margin: 20px auto;
  font: italic 26px/1.4 Georgia, serif;
  color: #fff;
  background: #245991;
}

.quote:after {
  content: "";
  position: absolute;
  top: 100%;
  right: 25px;
  border-width: 30px 30px 0 0;
  border-style: solid;
  border-color: #245991 transparent;
}

There’s nothing stopping you from adding some CSS3 to further enhance the effect for capable browsers. This could be adding rounded corners to the box or applying a skew transform to the triangle itself. Fiddle with the code in this example.

Creating CSS ‘ribbons’

Using the same principle, you can create a CSS ribbon effect without images or extra HTML. This time the effect uses 2 pseudo-element triangles. The HTML fragment is still very simple.

<div class="container">
    <h1>Simple CSS ribbon</h1>
    <p>[other content]</p>
</div>

You then need to use negative margins to pull the h1 outwards so that it extends over the padding and beyond the boundaries of the container div. The HTML fragment above can be styled using the following CSS:

.container {
  width: 400px;
  padding: 20px;
  margin: 20px auto;
  background: #fff;
}

.container h1 {
  position: relative;
  padding: 10px 30px;
  margin: 0 -30px 20px;
  font-size: 20px;
  line-height: 24px;
  font-weight: bold;
  color: #fff;
  background: #87A800;
}

From here, you only need to add the pseudo-element triangles to create the ‘wrapping’ appearance associated with ribbons. The :before and :after pseudo-elements share many styles, so you can simplify the code by only overriding the styles that differ between the two. In this case, the triangle created with the :after pseudo-element must appear on the opposite side of the heading, and will be a mirror image of the other triangle. So you need to override the shared styles that control its position and orientation.

.container h1:before,
.container h1:after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  border-width: 0 10px 10px 0;
  border-style: solid;
  border-color: transparent #647D01;
}

/* override shared styles */
.container h1:after {
  left: auto;
  right: 0;
  border-width: 0 0 10px 10px;
}

Fiddle with the code in this example.

Creating CSS folded corners

The final example of this form of pseudo-element hack creates a simple CSS folded-corner effect. A pseudo-element’s border properties are set to produce two differently-coloured touching triangles. One triangle is a slightly darker or lighter shade of the box’s background colour. The other triangle matches the background colour of the box’s parent (e.g. white). The pseudo-element is then positioned in the top right corner of its associated element to complete the effect.

.note {
  position: relative;
  padding: 20px;
  margin: 2em 0;
  color: #fff;
  background: #97C02F;
}

.note:before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  border-width: 0 16px 16px 0;
  border-style: solid;
  border-color: #658E15 #fff;
}

Varying the size of the borders will vary the size and angle of the folded-corner. Fiddle with the code in this example.

Pseudo background-crop

Although creating polygons with pseudo-elements can produce some popular effects without images, the possibilities are inherently limited. But this is only one type of :before and :after pseudo-element hack. Treated as extra background canvases, they can be used to fill some gaps in existing browser support for CSS features.

One of those features is the cropping of background images. In the future, it’s likely that you’ll be able to crop background images using fragment identifiers, as is proposed in the CSS Image Values Module Level 3 draft. But at the moment no browsers support the use of fragment identifiers with bitmap images. Until they do, you can make use of this CSS 2.1 hack to emulate background image cropping in modern browsers.

The principle behind a ‘pseudo background-crop‘ is to apply a background-image to a pseudo-element rather than directly to an element in the HTML document. One of the applications of this technique is to crop icons that are part of a sprite.

For example, a web app might allow users to ‘save’, ‘edit’, or ‘delete’ an item. The HTML involved might look something like this:

<ul class="actions">
  <li class="save"><a href="#">Save</a></li>
  <li class="edit"><a href="#">Edit</a></li>
  <li class="delete"><a href="#">Delete</a></li>
</ul>

To enhance the appearance of these ‘action’ links, it is common to see icons sitting alongside the anchor text. For argument’s sake, let’s say that the relevant icons are part of a sprite that is organised using a 16px × 16px grid.

The :before pseudo-element – with dimensions that match the sprite’s grid unit – can be used to crop and display each icon. The sprite is referenced as a background image and the background-position property is used to control the precise positioning of each icon to be shown.

.actions a:before {
  content: "";
  float: left;
  width: 16px;
  height: 16px;
  margin: 0 5px 0 0;
  background: url(sprite.png);
}

.save a:before { background-position: 0 0; }
.edit a:before { background-position: -16px 0; }
.delete a:before { background-position: -32px 0; }

Using pseudo-elements like this helps to avoid the need to either add liberal amounts of white space to sprites or use empty HTML elements to do the cropping. Fiddle with the code in this example.

Pseudo background-position

The CSS 2.1 specification limits the values of background-position to horizontal and vertical offsets from the top-left corner of an element. The CSS Backgrounds and Borders Module Level 3 working draft includes an improvement to the background-position property to allow offsets to be set from any side. However, Opera 11+ is currently the only browser to have implemented it.

But by using pseudo-elements, it’s possible to emulate positioning a background image from any side in any browser with adequate CSS 2.1 support –’pseudo background-position‘.

Once a pseudo-element is created, it must be absolutely positioned in front of the associated element’s background but behind its content, so as not to prevent users from being able to select text or click on links. This is done by setting a positive z-index on the element and a negative z-index on the pseudo-element.

#content {
  position: relative;
  z-index: 1;
}

#content:before {
  content: "";
  position: absolute;
  z-index: -1;
}

Now the pseudo-element can be sized and positioned to sit over any area within (or beyond) the element itself, without affecting its content. This is achieved by using any combination of values for the top, right, bottom, and left positional offsets, as well as the width, and height properties. It is the key to their flexibility.

In this example, a 200px × 300px background image is applied to the pseudo-element, which is also given dimensions that match those of the image. Since the pseudo-element is absolutely positioned, it can be offset from the bottom and right of the associated HTML element.

#content {
  position: relative;
  z-index: 1;
}

#content:before {
  content: "";
  position: absolute;
  z-index: -1;
  bottom: 10px;
  right: 10px;
  width: 200px;
  height: 300px;
  background: url(image.jpg);
}

Many other hacks and effects are possible using the :before and :after pseudo-elements, especially when combined with CSS3. Hopefully this introduction to pseudo-elements, and how they can be exploited, will have inspired you to experiment with them in your work.

The future of pseudo-elements

The way that pseudo-elements are used will continue to change as CSS does. Some new applications will emerge, and existing ones will fade away as browser implementation of ‘CSS3 modules’ continues to improve.

Generated content and pseudo-elements themselves are likely to undergo changes too. The CSS3 Generated and Replaced Content Module introduced a two-colon format for pseudo-elements (i.e., ::before) to help distinguish between pseudo-classes and pseudo-elements. But for compatibility with previous levels of CSS, pseudo-elements do not require two colons. Most modern browsers support both formats, but it is not supported by IE 8 and the single-colon format ensures greater backwards compatibility.

The proposed extensions to pseudo-elements included the addition of nested pseudo-elements (::before::before), multiple pseudo-elements (::after(2)), wrapping pseudo-elements (::outside), and the ability to insert pseudo-elements into later parts of the document (::alternate). However, the CSS3 Generated and Replaced Content Module is undergoing significant changes.

This article was originally published in .net magazine in April 2011




an

“Mobile first” CSS and getting Sass to help with legacy IE

Taking a “mobile first” approach to web development poses some challenges if you need to provide a “desktop” experience for legacy versions of IE. Using a CSS pre-processor like Sass can help.

As of Sass 3.2, there is another way of catering for IE, described by Jake Archibald.

One aspect of a “mobile first” approach to development is that your styles are usually gradually built up from a simple base. Each new “layer” of CSS adds presentational adjustments and complexity, via CSS3 Media Queries, to react to and make use of additional viewport space. However, IE 6/7/8 do not support CSS3 Media Queries. If you want to serve IE 6/7/8 something more than just the base CSS, then you need a solution that exposes the “enhancing” CSS to those browsers.

An existing option is the use of a CSS3 Media Query polyfill, such as Respond.js. However, there are some drawbacks to this approach (see the project README), such as the introduction of a JavaScript dependency and the XHRing of your style sheets, which may introduce performance or cross-domain security issues. Furthermore, adding support for CSS3 Media Queries is probably not necessary for these legacy browsers. The main concern is exposing the “enhancing” CSS.

Another method, which Jeremy Keith has described in his post on Windows mobile media queries, is to use separate CSS files: one basic global file, and an “enhancing” file that is referenced twice in the <head> of the document. The “enhancing” file is referenced once using a media attribute containing a CSS3 Media Query value. This prevents it being downloaded by browsers (such as IE 6/7/8) which do not support CSS3 Media Queries. The same file is then referenced again, this time wrapped in an IE conditional comment (without the use of a CSS3 Media Query value) to hide it from modern browsers. However, this approach becomes somewhat cumbersome, and introduces multiple HTTP requests, if you have multiple breakpoints in your responsive design.

Getting Sass to help

Sass 3.1 provides some features that help make this second approach more flexible. The general advantages of the Sass-based approach I’ve used are:

  1. You have full control over how your style sheets are broken up and reassembled.
  2. It removes the performance concerns of having to reference several separate style sheets for each breakpoint in the responsive design, simply to cater for IE 6/7/8.
  3. You can easily repeat large chunks of CSS in separate compiled files without introducing maintenance problems.

The basic idea is to produce two versions of your compiled CSS from the same core code. One version of your CSS includes CSS3 @media queries and is downloaded by modern browsers. The other version is only downloaded by IE 6/7/8 in a desktop environment and contains no CSS3 @media queries.

To do this, you take advantage of the fact that Sass can import and compile separate .scss/.sass files into a single CSS file. This allows you to keep the CSS rules used at any breakpoint completely separate from the @media query that you might want it to be a part of.

This is not a CSS3 Media Query polyfill, so one assumption is that IE 6/7/8 users will predominantly be using mid-size screens and should receive styles appropriate to that environment. Therefore, in the example below, I am making a subjective judgement by including all the breakpoint styles up to a width of 960px but withholding those for any breakpoints beyond that.

The ie.scss file imports numerous other files, each containing a layer of CSS that builds upon the previous each layer of CSS. No CSS3 @media queries are contained within the files or the ie.scss file. It then compiles to a single CSS file that is designed to be served only to IE 6/7/8.

// ie.scss

@import "base";
@import "320-up";
@import "480-up";
@import "780-up";
@import "960-up";

The style.scss file imports the code for each breakpoint involved in the design (including any beyond the limit imposed for legacy versions of IE) but nests them within the relevant CSS3 @media query. The compiled version of this file is served to all browsers apart from IE 6/7/8 and IEMobile.

// style.scss

@import "base";
@media (min-width:320px) {
    @import "320-up"; }
@media (min-width:480px) {
    @import "480-up"; }
@media (min-width:780px) {
    @import "780-up"; }
@media (min-width:960px) {
    @import "960-up"; }
@media (min-width:1100px) {
    @import "1100-up"; }

The resulting CSS files can then be referenced in the HTML. It is important to hide the ie.css file from any IE-based mobile browsers. This ensures that they do not download the CSS meant for desktop versions of IE.

<!--[if (gt IE 8) | (IEMobile)]><!-->
<link rel="stylesheet" href="/css/style.css">
<!--<![endif]-->

<!--[if (lt IE 9) & (!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css">
<![endif]-->

This Sass-enabled approach works just as well if you need to serve a basic style sheet for mobiles without CSS3 Media Query support, and prevent those devices from downloading the CSS used to adapt the layout to wider viewports. For example, you can avoid importing base.scss into the ie.scss and style.scss files. It can then be referenced separately in the HTML.

<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="/css/style.css" media="(min-width:320px)">

<!--[if (lt IE 9) & (!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css">
<![endif]-->

You’ll notice that I didn’t wrap the style.css reference in a conditional comment to hide it from legacy versions of IE. It’s not necessary this time because the value of the media attribute is not understood by legacy versions of IE, and the style sheet will not be downloaded.

In different circumstances, different combinations of style sheets and media attribute values will be more appropriate.

Summary

Even if you want to don’t want to use any of the Sass or SCSS syntax, the pre-processor itself can help you to write your CSS in a “mobile first” manner (with multiple breakpoints), provide a “desktop” experience for IE 6/7/8, and avoid some of the performance or maintenance concerns that are sometimes present when juggling the two requirements.

I’m relatively new to using Sass, so there may be even better ways to achieve the same result or even to prevent the inclusion of IE-specific CSS unless the file is being compiled into a style sheet that only IE will download.




an

CSS: the cascade, specificity, and inheritance

What is the cascade?

The cascade is a mechanism for determining which styles should be applied to a given element, based on the rules that have cascaded down from various sources.

The cascade takes importance, origin, specificity, and source order of style rules into account. It assigns a weight to each rule. When multiple rules apply to a given element, the rule with the greatest weight takes precedence. The result is an unambiguous way to determine the value of a given element/property combination.

Browsers apply the following sorting logic:

  • Find all declarations that apply to a given element/property combination, for the target media type.
  • Sort declarations according to their importance (normal or important) and origin (author, user, or user agent). From highest to lowest precedence:

    1. user !important declarations
    2. author !important declarations
    3. author normal declarations
    4. user normal declarations
    5. user agent declarations
  • If declarations have the same importance and source, sort them by selector specificity.

  • Finally, if declarations have the same importance, source, and specificity, sort them by the order they are specified in the CSS. The last declaration wins.

What is specificity?

Specificity is a method of conflict resolution within the cascade.

Specificity is calculated in a very particular way, based on the values of 4 distinct categories. For explanatory purposes, the CSS2 spec represents these categories using the letters a, b, c, and d. Each has a value of 0 by default.

  • a is equal to 1 if the declaration comes from a style attribute in the HTML (“inline styles”) rather than a CSS rule with a selector.
  • b is equal to the number of ID attributes in a selector.
  • c is equal to the number of other attributes and pseudo-classes in a selector.
  • d is equal to the number of elements and pseudo-elements in a selector.

The specificity is given by concatenating all 4 resulting numbers. More specific selectors take precedence over less specific ones.

For example, the selector #id .class[href] element:hover contains:

  • 1 ID (b is 1)
  • 1 class, 1 attribute selector, and 1 pseudo-class (c is 3)
  • 1 element (d is 1)

Therefore, it has a specificity of 0,1,3,1. Note that a selector containing a single ID (0,1,0,0) will have a higher specificity than one containing any number of other attributes or elements (e.g., 0,0,10,20). This is one of the reasons why many modern CSS architectural patterns avoid using IDs for styling purposes.

What is inheritance?

Inheritance is distinct from the cascade and involves the DOM tree.

Inheritance is the process by which elements inherit the the values of properties from their ancestors in the DOM tree. Some properties, e.g. color, are automatically inherited by the children of the element to which they are applied. Each property defines whether it will be automatically inherited.

The inherit value can be set for any property and will force a given element to inherit its parent element’s property value, even if the property is not normally inherited.

About !important

The above should make it apparent that !important is a separate concept to specificity. It has no effect on the specificity of a rule’s selector.

An !important declaration has a greater precedence than a normal declaration (see the previously mentioned cascade sorting logic), even declarations contained in an element’s style attribute.

[CSS terminology reference]

Translations




an

Another CSS image replacement technique

A new image replacement technique was recently added to the HTML5 Boilerplate project. This post explains how it works and how it compares to alternative image replacement techniques.

[15 December 2012] This technique is no longer used in HTML5 Boilerplate. It’s been replaced by another, more reliable approach.

Here’s the CSS behind the recent update to the image replacement helper class in HTML5 Boilerplate. It has also made its way into the Compass framework.

.ir {
  font: 0/0 a;
  text-shadow: none;
  color: transparent;
}

What does each declaration do?

  • font:0/0 a – a shorthand property that zeros out the font size and line-height. The a value acts as a very short font-family (an idea taken from the BEM implementation of this method). The CSS validator complains that using 0/0 in the shorthand font property is not valid, but every browser accepts it and this appears to be an error in the validator. Using font:0px/0 a passes validation but it displayed as font:0/0 a in the code that the validator flags as valid.
  • text-shadow:none – makes sure that any inherited text shadow is removed for the text. This prevents the chance of any text shadow colors showing over the background.
  • color:transparent – needed for browsers than don’t completely crush the text to the point of being invisible. Safari 4 (extremely rare) is an example of such a browser. There may also be mobile browsers than require this declaration. IE6/7/8 don’t recognise this value for color, but fortunately IE7/8 don’t show any trace of the text. IE6 shows a faint trace.

In the HTML5 Boilerplate image replacement helper, we’ve also removed any border and background-color that may be on the element. This makes it easier to use the helper class on elements like button or with links that may included background or border properties as part of a design decision.

Benefits over text-indent methods

The new technique avoids various problems with any text-indent method, including the one proposed by Scott Kellum to avoid iPad 1 performance problems related to large negative text indents.

  • Works in IE6/7 on inline-block elements. Techniques based on text indentation are basically “broken”, as shown by this test case: http://jsfiddle.net/necolas/QZvYa/show/
  • Doesn’t result in any offscreen box being created. The text-indent methods result in a box being drawn (sometimes offscreen) for any text that have been negatively or positively indented. It can sometimes cause performance problems but the font-based method sidesteps those concerns.
  • No need to specify a text-alignment and hide the overflow since the text is crushed to take up no space.
  • No need to hide br or make all fallback HTML display:inline to get around the constraints of using a text indentation. This method is not affected by those problems.
  • Fewer styles are needed as a result of these improvements.

Drawbacks

No image replacement hack is perfect.

  • Leaves a very small trace of the text in IE6.
  • This approach means that you cannot use em units for margins on elements that make use of this image replacement code. This is because the font size is set to 0.
  • Windows-Eyes has a bug that prevents the reading of text hidden using this method. There are no problems with all other screenreaders that have been tested. Thanks to @jkiss for providing these detailed results and to @wilto for confirming this technique works for JAWS 12 in IE 6/7/8 and Firefox 4/5/6.
  • Like so many IR methods, it doesn’t work when CSS is loaded but images are not.
  • Text may not be hidden if a visitor is using a user style sheet which has explicitly set important font-size declarations for the element type on which you have applied the IR class.

It’s worth noting that the NIR image replacement technique avoids these drawbacks, but lacks support in IE6/7.

Closing comments

I’ve been using this technique without significant problems for nearly a year, ever since Jonathan Neal and I used it in a clearfix experiment. The BEM framework also makes use of it for their icon components. The core idea was even proposed back in 2003 but the browser quirks of the day may have prevented wider use.

If you come across any problems with this technique, please report them at the HTML5 Boilerplate GitHub issue tracker and include a test case when appropriate.

Translations




an

About HTML semantics and front-end architecture

A collection of thoughts, experiences, ideas that I like, and ideas that I have been experimenting with over the last year. It covers HTML semantics, components and approaches to front-end architecture, class naming patterns, and HTTP compression.

About semantics

Semantics is the study of the relationships between signs and symbols and what they represent. In linguistics, this is primarily the study of the meaning of signs (such as words, phrases, or sounds) in language. In the context of front-end web development, semantics are largely concerned with the agreed meaning of HTML elements, attributes, and attribute values (including extensions like Microdata). These agreed semantics, which are usually formalised in specifications, can be used to help programmes (and subsequently humans) better understand aspects of the information on a website. However, even after formalisation, the semantics of elements, attributes, and attribute values are subject to adaptation and co-option by developers. This can lead to subsequent modifications of the formally agreed semantics (and is an HTML design principle).

Distinguishing between different types of HTML semantics

The principle of writing “semantic HTML” is one of the foundations of modern, professional front-end development. Most semantics are related to aspects of the nature of the existing or expected content (e.g. h1 element, lang attribute, email value of the type attribute, Microdata).

However, not all semantics need to be content-derived. Class names cannot be “unsemantic”. Whatever names are being used: they have meaning, they have purpose. Class name semantics can be different to those of HTML elements. We can leverage the agreed “global” semantics of HTML elements, certain HTML attributes, Microdata, etc., without confusing their purpose with those of the “local” website/application-specific semantics that are usually contained in the values of attributes like the class attribute.

Despite the HTML5 specification section on classes repeating the assumed “best practice” that…

…authors are encouraged to use [class attribute] values that describe the nature of the content, rather than values that describe the desired presentation of the content.

…there is no inherent reason to do this. In fact, it’s often a hindrance when working on large websites or applications.

  • Content-layer semantics are already served by HTML elements and other attributes.
  • Class names impart little or no useful semantic information to machines or human visitors unless it is part of a small set of agreed upon (and machine readable) names – Microformats.
  • The primary purpose of a class name is to be a hook for CSS and JavaScript. If you don’t need to add presentation and behaviour to your web documents, then you probably don’t need classes in your HTML.
  • Class names should communicate useful information to developers. It’s helpful to understand what a specific class name is going to do when you read a DOM snippet, especially in multi-developer teams where front-enders won’t be the only people working with HTML components.

Take this very simple example:

<div class="news">
    <h2>News</h2>
    [news content]
</div>

The class name news doesn’t tell you anything that is not already obvious from the content. It gives you no information about the architectural structure of the component, and it cannot be used with content that isn’t “news”. Tying your class name semantics tightly to the nature of the content has already reduced the ability of your architecture to scale or be easily put to use by other developers.

Content-independent class names

An alternative is to derive class name semantics from repeating structural and functional patterns in a design. The most reusable components are those with class names that are independent of the content.

We shouldn’t be afraid of making the connections between layers clear and explicit rather than having class names rigidly reflect specific content. Doing this doesn’t make classes “unsemantic”, it just means that their semantics are not derived from the content. We shouldn’t be afraid to include additional HTML elements if they help create more robust, flexible, and reusable components. Doing so does not make the HTML “unsemantic”, it just means that you use elements beyond the bare minimum needed to markup the content.

Front-end architecture

The aim of a component/template/object-oriented architecture is to be able to develop a limited number of reusable components that can contain a range of different content types. The important thing for class name semantics in non-trivial applications is that they be driven by pragmatism and best serve their primary purpose – providing meaningful, flexible, and reusable presentational/behavioural hooks for developers to use.

Reusable and combinable components

Scalable HTML/CSS must, by and large, rely on classes within the HTML to allow for the creation of reusable components. A flexible and reusable component is one which neither relies on existing within a certain part of the DOM tree, nor requires the use of specific element types. It should be able to adapt to different containers and be easily themed. If necessary, extra HTML elements (beyond those needed just to markup the content) and can be used to make the component more robust. A good example is what Nicole Sullivan calls the media object.

Components that can be easily combined benefit from the avoidance of type selectors in favour of classes. The following example prevents the easy combination of the btn component with the uilist component. The problems are that the specificity of .btn is less than that of .uilist a (which will override any shared properties), and the uilist component requires anchors as child nodes.

.btn { /* styles */ }
.uilist { /* styles */ }
.uilist a { /* styles */ }
<nav class="uilist">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a class="btn" href="#">Login</a>
</nav>

An approach that improves the ease with which you can combine other components with uilist is to use classes to style the child DOM elements. Although this helps to reduce the specificity of the rule, the main benefit is that it gives you the option to apply the structural styles to any type of child node.

.btn { /* styles */ }
.uilist { /* styles */ }
.uilist-item { /* styles */ }
<nav class="uilist">
    <a class="uilist-item" href="#">Home</a>
    <a class="uilist-item" href="#">About</a>
    <span class="uilist-item">
        <a class="btn" href="#">Login</a>
    </span>
</nav>

JavaScript-specific classes

Using some form of JavaScript-specific classes can help to reduce the risk that thematic or structural changes to components will break any JavaScript that is also applied. An approach that I’ve found helpful is to use certain classes only for JavaScript hooks – js-* – and not to hang any presentation off them.

<a href="/login" class="btn btn-primary js-login"></a>

This way, you can reduce the chance that changing the structure or theme of components will inadvertently affect any required JavaScript behaviour and complex functionality.

Component modifiers

Components often have variants with slightly different presentations from the base component, e.g., a different coloured background or border. There are two mains patterns used to create these component variants. I’m going to call them the “single-class” and “multi-class” patterns.

The “single-class” pattern

.btn, .btn-primary { /* button template styles */ }
.btn-primary { /* styles specific to save button */ }

<button class="btn">Default</button>
<button class="btn-primary">Login</button>

The “multi-class” pattern

.btn { /* button template styles */ }
.btn-primary { /* styles specific to primary button */ }

<button class="btn">Default</button>
<button class="btn btn-primary">Login</button>

If you use a pre-processor, you might use Sass’s @extend functionality to reduce some of the maintenance work involved in using the “single-class” pattern. However, even with the help of a pre-processor, my preference is to use the “multi-class” pattern and add modifier classes in the HTML.

I’ve found it to be a more scalable pattern. For example, take the base btn component and add a further 5 types of button and 3 additional sizes. Using a “multi-class” pattern you end up with 9 classes that can be mixed-and-matched. Using a “single-class” pattern you end up with 24 classes.

It is also easier to make contextual tweaks to a component, if absolutely necessary. You might want to make small adjustments to any btn that appears within another component.

/* "multi-class" adjustment */
.thing .btn { /* adjustments */ }

/* "single-class" adjustment */
.thing .btn,
.thing .btn-primary,
.thing .btn-danger,
.thing .btn-etc { /* adjustments */ }

A “multi-class” pattern means you only need a single intra-component selector to target any type of btn-styled element within the component. A “single-class” pattern would mean that you may have to account for any possible button type, and adjust the selector whenever a new button variant is created.

Structured class names

When creating components – and “themes” that build upon them – some classes are used as component boundaries, some are used as component modifiers, and others are used to associate a collection of DOM nodes into a larger abstract presentational component.

It’s hard to deduce the relationship between btn (component), btn-primary (modifier), btn-group (component), and btn-group-item (component sub-object) because the names don’t clearly surface the purpose of the class. There is no consistent pattern.

In early 2011, I started experimenting with naming patterns that help me to more quickly understand the presentational relationship between nodes in a DOM snippet, rather than trying to piece together the site’s architecture by switching back-and-forth between HTML, CSS, and JS files. The notation in the gist is primarily influenced by the BEM system‘s approach to naming, but adapted into a form that I found easier to scan.

Since I first wrote this post, several other teams and frameworks have adopted this approach. MontageJS modified the notation into a different style, which I prefer and currently use in the SUIT framework:

/* Utility */
.u-utilityName {}

/* Component */
.ComponentName {}

/* Component modifier */
.ComponentName--modifierName {}

/* Component descendant */
.ComponentName-descendant {}

/* Component descendant modifier */
.ComponentName-descendant--modifierName {}

/* Component state (scoped to component) */
.ComponentName.is-stateOfComponent {}

This is merely a naming pattern that I’m finding helpful at the moment. It could take any form. But the benefit lies in removing the ambiguity of class names that rely only on (single) hyphens, or underscores, or camel case.

A note on raw file size and HTTP compression

Related to any discussion about modular/scalable CSS is a concern about file size and “bloat”. Nicole Sullivan’s talks often mention the file size savings (as well as maintenance improvements) that companies like Facebook experienced when adopting this kind of approach. Further to that, I thought I’d share my anecdotes about the effects of HTTP compression on pre-processor output and the extensive use of HTML classes.

When Twitter Bootstrap first came out, I rewrote the compiled CSS to better reflect how I would author it by hand and to compare the file sizes. After minifying both files, the hand-crafted CSS was about 10% smaller than the pre-processor output. But when both files were also gzipped, the pre-processor output was about 5% smaller than the hand-crafted CSS.

This highlights how important it is to compare the size of files after HTTP compression, because minified file sizes do not tell the whole story. It suggests that experienced CSS developers using pre-processors don’t need to be overly concerned about a certain degree of repetition in the compiled CSS because it can lend itself well to smaller file sizes after HTTP compression. The benefits of more maintainable “CSS” code via pre-processors should trump concerns about the aesthetics or size of the raw and minified output CSS.

In another experiment, I removed every class attribute from a 60KB HTML file pulled from a live site (already made up of many reusable components). Doing this reduced the file size to 25KB. When the original and stripped files were gzipped, their sizes were 7.6KB and 6KB respectively – a difference of 1.6KB. The actual file size consequences of liberal class use are rarely going to be worth stressing over.

How I learned to stop worrying…

The experience of many skilled developers, over many years, has led to a shift in how large-scale website and applications are developed. Despite this, for individuals weaned on an ideology where “semantic HTML” means using content-derived class names (and even then, only as a last resort), it usually requires you to work on a large application before you can become acutely aware of the impractical nature of that approach. You have to be prepared to disgard old ideas, look at alternatives, and even revisit ways that you may have previously dismissed.

Once you start writing non-trivial websites and applications that you and others must not only maintain but actively iterate upon, you quickly realise that despite your best efforts, your code starts to get harder and harder to maintain. It’s well worth taking the time to explore the work of some people who have proposed their own approaches to tackling these problems: Nicole’s blog and Object Oriented CSS project, Jonathan Snook’s Scalable Modular Architecture CSS, and the Block Element Modifier method that Yandex have developed.

When you choose to author HTML and CSS in a way that seeks to reduce the amount of time you spend writing and editing CSS, it involves accepting that you must instead spend more time changing HTML classes on elements if you want to change their styles. This turns out to be fairly practical, both for front-end and back-end developers – anyone can rearrange pre-built “lego blocks”; it turns out that no one can perform CSS-alchemy.




an

Moving from London to San Francisco

I recently moved from London to San Francisco to work at Twitter, as a Software Engineer. This is a rough guide – in the spirit of @chanian’s tutorial for Canadians – based on my experience of relocating, the mistakes I made along the way, and some information I wish I’d had. Use it at your own risk – don’t assume any legal truths; research things for yourself before making decisions!

I’m not going to cover anything about the US visa process. The company that has offered you employment in the US is likely to work with immigration lawyers who will handle (or guide you through) the visa application and processing. I’m also going to assume that your employer is providing temporary accommodation or that you are organising your own (e.g., via Airbnb) while you search for an apartment. Most of this article relates to things you will need to do once you arrive in San Francisco and soon after, but that you should spend some time thinking about beforehand.

Get a phone

You’ll need a US mobile/cell number pretty quickly, especially if you’re apartment-hunting.

The US telecom market isn’t great and will leave you nostalgic for the halcyon days of the EU-regulated, pro-consumer market you’ve left behind. For example, it’s now illegal to unlock a phone from a carrier unless you have that carrier’s permission to do so. Furthermore, if you do get a phone from a carrier (as part of your contract deal), you should be aware of whether or not you will be locked into a proprietary network, like Verison’s CDMA. Without a US credit history, you should expect to pay a sizable deposit when entering into a contract.

One way to reduce the cost of a phone contract is to bring your own phone to the party. If you bring a phone from the UK, make sure to check that your charger will work on US voltage. With an unlocked, GSM-supporting phone you can look to carriers like T-Mobile who offer various “value” and no-annual-contract plans. These prices are significantly cheaper because they don’t subsidise the purchase of a new phone. You’re likely to find “unlimited” data plans easier to come by than they are in the UK.

You’re shit-out-of-luck if you’re thinking you’d prefer a European-style pay-as-you-go (PAYG) approach. The options are thin on the ground. Any airtime you buy means just that – any time you spend talking or texting – so you pay to send and receive calls or SMS’s. My experience suggests that some networks recycle phone numbers or sell on your details. I still receive random texts addressed to previous owners of my phone number, and get messages from marketing companies who have miraculously acquired my personal details, an irritation that is compounded by the fact that it costs you money to be harassed.

If you’re determined to go the PAYG route, the nearest US equivalent is probably AT&T’s GoPhone SIM or Net10. You’ll have to purchase a phone and credit up front; top ups can be purchased in store, at some supermarkets, or done over the phone. This may also be the first time you encounter the US concept of a “restocking fee” – a method of dissuading you from returning items by charging you to do so. The restocking fee for the burner phone I first purchased was almost as much as the phone itself.

Open a bank account, transfer money

Make this a top priority. You should open a bank account as soon as you arrive in the US, especially as some banks will initially let you do so without a Social Security Number or permanent address.

Until you open a US bank account, you’ll be haemorrhaging money on fees levied by your UK bank for dollar transactions, and subject to poor exchange rates.

Choose a bank

San Francisco has a large range of different bank brands to choose from, but you’re probably best sticking to the big name banks that have branches and ATMs throughout the city, such as Bank of America, Chase, or Wells Fargo. There are co-ops and niche services if that’s your thing. Be sure to do some preparatory research on which bank is best suited to your needs. It’s also worth checking if your bank in the UK has a reciprocal agreement with any bank operating in San Francisco; it may cut down the cost of moving your money. Friends recommended going with either Bank of America or Chase. I went with Bank of America, where the customer service was personal and friendly.

Banking fees are a matter of course in the US. In contrast to the UK, you’ll almost certainly be charged for withdrawing money from any ATMs that aren’t owned by your bank. You have to buy cheque books (“check” in American English) and pay a fee to transfer your money to accounts outside your bank. Accounts usually involve a monthly fee, although this is waived in certain situations, such as setting up your salary to be directly deposited. Expect to set up a current (“checking”) and savings account, and to be asked to make a minimum cash deposit to complete the process (at Bank of America it was $100).

Once you’re all set up, your debit card will be sent in the post – so make sure you’ll be at that address for at least another week. In the meantime you may get a temporary cash card to get at what you’ve already deposited. Even if you transfer more money in, your bank can limit the amount you can withdraw within the first 30 days of the account being open – presumably to combat fraud/laundering.

Transfer money

It’s essential that you transfer money from your UK bank as soon as possible. There are many factors to consider when calculating how much money you want to transfer.

  • You may enter the US up to 10 days before your visa is valid and you can start work.
  • You need money for food, transport, going out, a phone (and deposit), apartment applications, an apartment deposit, buying furniture, etc.
  • You might not be able to get paid until you have a Social Security Number.
  • You’re unlikely to get paid until the middle or end of the month you start working.
  • You’re very likely to get your first pay cheque given to you as a real cheque; your bank is then likely to withhold the vast majority of the cheque’s value for up to 28 days.
  • It will cost you several thousand dollars – a deposit and at least one month of rent – to secure an apartment. In general, landlords will not accept a UK banking cheque.
  • You’ll have to buy furniture and general household items if you aren’t shipping any from the UK.

All in all, this means you may end up without any significant US-earned money in your account for 30-45 days while making some of the biggest expenses you’re likely to have made for a while.

Transferring money to a US bank account can be done online via wire transfer between banks. Unfortunately, my bank in the UK – Santander – didn’t allow online wire transfers so I had to look for alternatives. You may want to research this prior to leaving the UK!

The Post Office provide a simple, secure, and fee-free service, but a poorer exchange rate. Looking around, I came across Currencyfair – a peer-to-peer currency exchange service. They provide online quotes without the need to sign up, they were very prompt and helpful in their replies to questions I had, and the exchange rate was very good. Overall, I saved quite a bit of money and I’d rely on them in the future.

Get a Clipper card

The Clipper card is San Francisco’s equivalent of London’s Oyster card. Getting one will take some of the pain out of using the various modes of public transport in San Francisco. You can get a Clipper card online and I’d suggest setting up “Autoload” (you’ll need a bank account) to get the card for free and never worry about remembering to top up your credit. Alternatively, you can buy them on the high street from shops like Walgreens.

Get a Social Security Number

Social Security recommend that you only apply for a Social Security Number once you’ve been in the US over 10 days.

My experience was that the process is quick and simple. You complete a short SSN application form ahead of time and take it to the nearest Social Security office along with the documentation they advise you to bring. Arrive first thing in the morning to avoid any wait. It can take a few weeks for your Social Security card to arrive so you may want to have it sent to your employer’s address if you don’t have a permanent address yet.

Once you have your Social Security Card, you should keep it safe and be judicious in giving your SSN out. However, you should provide it to your bank and employer as soon as possible.

Find somewhere to live

Living in the city of San Francisco is just one of the (more expensive) options available to you. I chose to live in the city but many of my friends and colleagues live in other areas, like the East Bay. Have a look around before making up your mind.

Rent is very expensive in San Francisco, even compared to prices in London, especially since it’s very rare to find furnished accommodation. It also appears to be rising at a staggering rate. However, buildings constructed before June 1979 are covered by San Francisco Rent Control which heavily constrains the rate at which your rent can increase once you become a tenant. Therefore, it’s worth taking the time to find somewhere that you could imagine living for a few years.

The rental market is extremely competitive. Many places rely on one-off, brief, herd-style viewings where you’re in the apartment with half a dozen other desperate people at the same time, and more arriving every minute. People hand over all their paperwork and a cash application fee (if applicable) there and then.

Things are made slightly harder because you’re unlikely to have any US credit history, which is something quite important over here. But an offer letter and salary details from a tech company seems to put you in good shape. It’s in your best interest to put together a dossier of papers to provide alongside any application you make. You should include scans of your employer’s offer letter, your visa, and ideally character references from a previous landlord, etc. Print out several copies to take with you to viewings. You might have to pay $30-$40 to make an application (which is meant to cover credit history checks), but I never did.

I found that using Craigslist or a listing aggregator like Lovely was the best way to find apartments for rent in the city. They will also help you to narrow your focus to the neighbourhoods that you’re most interested in (spend some time learning about the city). Before moving to San Francisco, I heard a lot of stories about how it was essential – if you are to have any hope – to be “first” to make contact with the poster of a listing, but my experience was that you’re generally given the date and time of a mass-viewing to attend. This means that making a good impression in person, and having a bit of a chat with your potential landlord or building-manager, is likely to improve your chances and help you make a decision. Be prepared for it to take a while to find an apartment – it took me over a month of searching.

Once you’ve found a place to rent and signed all the paperwork, call PG&E to create an account to pay for your heat and electricity. You can set up e-bills and automatic payments online once your account has been processed. It’s a good idea to sort out an ISP before you move in – I went with Sonic.net. Again, the monthly cost (which I was told includes 17 different taxes and “renting” of the router) is a little higher than you’d expect in the UK, and you can expect to pay an installation fee. Other things to do: get Renters Insurance and have your bank automatically mail out your monthly-rent check to your landlord or building manager. All these things are quick and easy to do.

If you’re interested in your renters rights, you can search the California Department of Consumer Affairs for information.

Buying stuff for your place

You’re going to need furniture and basic household items. There’s always Ikea, which is located in Emeryville across the bay. If you have any previous Ikea experience, you’ll know that it’s one of the most stressful shopping experiences imaginable. The Ikea in Emeryville is even worse but the prices are pretty good. You can get there by bus from San Francisco and have large items delivered, or sort out your own transport.

Other stores to look at include West Elm and Crate & Barrel; they sell nicer things but are significantly more expensive. Alternatively, there are a lot of independent and second-hand furniture shops in San Francisco, particularly in the Mission district and a few along Van Ness. They’re well worth checking out. Van Ness also has 3 or 4 stores that sell mattresses – Sleep Train came particularly well recommended. I’d suggest that you leverage the lower costs of similar mattresses online in order to significantly reduce the price of your purchase, while benefiting from the great service, free delivery, and returns policy of the high-street stores. And if you have no idea what you’re doing: home decor tips, infographics, and cheat sheets

Get a California I.D.

Once you have your SSN and have found a permanent address, you should apply for a California I.D. at the DMV. This is handy if you don’t want to carry your passport (with visa) around and don’t have alternative I.D., such as a driver’s licence. You should register for an appointment to avoid a long wait in line. It can take up to 60 days for your California I.D. to arrive.

Get a credit card

The U.S. revolves around consumer credit. You need to start building up a credit history as soon as possible if you want to avoid paying large deposits or higher prices. Ask your bank about the soonest that you can apply for a credit card and then start using it – buying on credit even if you don’t need to.

Inform HMRC and the Student Loans Company

Once you’re settled, you should make time to inform HMRC that you’ve left the UK. They’ll be able to assess your tax status. If you are repaying student loans, after 3 months in the US you’re expected to contact the Student Loans Company by completing an overseas income assessment form. They will then work out your repayments.

Welcome to the United States of America

Hopefully you settle in within a couple of months and get to know San Francisco. There are many faces to this city, but the social scene is pretty diverse and there are many restaurants, bars, cafes, parks, and attractions – plenty of places to explore and things to do while you find your feet.




an

Walking around San Francisco on July 4th

For the first time since coming back to San Francisco in January, I had everything I needed for a saunter across the city in the sun: a means of taking photos / videos, a pair of sunglasses, no work, no plans, and no excuse.

On the morning of July 4th, I decided to spend the next couple of days offline. I read a book, and decided to go for a walk the rest of the day. I didn’t have any expectations or intended destination. I left my apartment at 2pm and decided to walk west, as I haven’t spent any proper time on that side of the city.

I passed through a couple of small parks and quiet neighbourhoods before hitting the edge of The Presidio.

At this point, I realised how long it had been since I’d seen a large expanse of something approximating nature. The Presidio was beautifully tranquil, with just a handful of people strolling or running through the trees. Walking off the trails, I saw a lizard for the first time in years; probably a San Francisco Alligator Lizard.

I exited The Presidio somewhere near the golf course and picked a long road to keep walking west.

On the way, I hit a main road and stood at the traffic lights. While I waited a young woman walking her dog struck up the first of several impromptu conversations I had with strangers that day. She must have seen me looking around for the street name, as she asked, “Are you lost? Are you a tourist? Where are you going?”

“I’m not sure. That way”, I said pointing down the long road before us.

She laughed. “See, you are lost!”

We chatted for a few blocks before our paths diverged. She told me that I would find some nice trails, and a good view of the Golden Gate Bridge, in the woodland near Lands End. It was dead ahead for another 30 minutes. So that’s where I went.

I hit the trails at about 4:30pm. It must have been close to perfect weather. Really sunny, warm, only a mild breeze, and the bay was completely clear. I wandered around for over an hour; perching near the edge of cliffs, taking in the sight of the Golden Gate Bridge on my right and a vast expanse of ocean to my left. Such a relaxing place.

I made time for a Dorsey-like Vine (my first Vine)…

On the way back, I crossed a road to take a photo. A post-middle-age man crossed my path, struck up a conversation, and began to tell me about his life in San Francisco “back in the day”. As if he could peer into my soul, he assured me that there was nothing wrong with being a software engineer (although he did initially think I was an estate agent; that was one of the first things he said to me).

My spirits further lifted by a stranger’s validation, I continued home. For last 30 minutes all I could think about was lying down, resting my feet, and eating. I’d been walking for nearly 6 hours. I’ll definitely do it again, but a skateboard would be helpful next time.




an

How to test React components using Karma and webpack

I’m working on a project at Twitter that uses React and webpack. After a few conversations with @sokra last year, this is the setup I put in place for testing React components (authored using JSX and ES6) using Karma.

Dependencies

You’ll need to install various packages. It looks like a lot of dependencies, but all the non-Karma packages will be necessary for general module bundling during development.

Full set of required packages:

webpack entry file

If you use webpack-specific features in your modules (e.g., loaders, plugins) you will need to use webpack to build a test bundle. The fastest and simplest approach is to create a single, test-specific entry file.

Create a file named tests.bundle.js. Within this file, you create a webpack context to match all the files that conform to a naming pattern – in this case *.spec.js(x).

var context = require.context('.', true, /.+.spec.jsx?$/);
context.keys().forEach(context);
module.exports = context;

Next, you point Karma to this file.

Karma config

Karma is configured using a karma.conf.js file. The browsers, plugins, and frameworks are specified in the standard way.

Point Karma at the tests.bundle.js file, and run it through the relevant preprocessor plugins (see example below).

The karma-webpack plugin relies on 2 custom properties of the Karma config: webpack and webpackMiddleware. The value of the former must be a webpack config object.

module.exports = function (config) {
  config.set({
    browsers: [ 'Chrome' ],
    // karma only needs to know about the test bundle
    files: [
      'tests.bundle.js'
    ],
    frameworks: [ 'chai', 'mocha' ],
    plugins: [
      'karma-chrome-launcher',
      'karma-chai',
      'karma-mocha',
      'karma-sourcemap-loader',
      'karma-webpack',
    ],
    // run the bundle through the webpack and sourcemap plugins
    preprocessors: {
      'tests.bundle.js': [ 'webpack', 'sourcemap' ]
    },
    reporters: [ 'dots' ],
    singleRun: true,
    // webpack config object
    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          {
            exclude: /node_modules/,
            loader: 'babel-loader,
            test: /.jsx?$/
          }
        ],
      }
    },
    webpackMiddleware: {
      noInfo: true,
    }
  });
};

Rather than duplicating your webpack config, you can require it in the Karma config file and override the devtool value to get sourcemaps working.

var webpackConfig = require('./webpack.config');
webpackConfig.devtool = 'inline-source-map';

module.exports = function (config) {
  config.set({
    ...
    webpack: webpackConfig
  });
};

That’s all you need to do to configure Karma to use webpack to load your JSX, ES6 React components.




an

Using canvas to fix SVG scaling in Internet Explorer

Internet Explorer 9–11 suffer from various bugs that prevent proper scaling of inline SVG’s. This is particularly problematic for SVG icons with variable widths. This is the canvas-based hack I’ve been using to work around the issue.

A popular way to use SVG icons is to generate a spritemap of SVG symbol‘s that you then reference from elsewhere in a document. Most articles on the topic assume your icon dimensions are uniformly square. Twitter’s SVG icons (crafted by @sofo) are variable width, to produce consistent horizontal whitespace around the vectors.

Most browsers will preserve the intrinsic aspect ratio of an SVG. Ideally, I want to set a common height for all the icons (e.g., 1em), and let the browser scale the width of each icon proportionally. This also makes it easy to resize icons in particular contexts – just change the height.

Unfortunately, IE 9–11 do not preserve the intrinsic aspect ratio of an inline SVG. The svg element will default to a width of 300px (the default for replaced content elements). This means it’s not easy to work with variable-width SVG icons. No amount of CSS hacking fixed the problem, so I looked elsewhere – and ended up using canvas.

canvas and aspect ratios

A canvas element – with height and width attributes set – will preserve its aspect ratio when one dimension is scaled. The example below sets a 3:1 aspect ratio.

<canvas height="1" width="3"></canvas>

You can then scale the canvas by changing either dimension in CSS.

canvas {
  display: block;
  height: 2rem;
}

Demo: proportional scaling of canvas.

Fixing SVG scaling in IE

This makes canvas useful for creating aspect ratios. Since IE doesn’t preserve the intrinsic aspect ratio of SVG icons, you can use canvas as a shim. A canvas of the correct aspect ratio provides a scalable frame. The svg can then be positioned to fill the space created by this frame.

The HTML is straightforward:

<div class="Icon" role="img" aria-label="Twitter">
  <canvas class="Icon-canvas" height="1" width="3"></canvas>
  <svg class="Icon-svg">
    <use fill="currentcolor" xlink:href="#icon-twitter"></use>
  </svg>
</div>

So is the CSS:

.Icon {
  display: inline-block;
  height: 1em; /* default icon height */
  position: relative;
  user-select: none;
}

.Icon-canvas {
  display: block;
  height: 100%;
  visibility: hidden;
}

.Icon-svg {
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
}

Setting the canvas height to 100% means it will scale based on the height of the component’s root element – just as SVG’s do in non-IE browsers. Changing the height of the Icon element scales the inner SVG icon while preserving its 3:1 aspect ratio.

Demo: proportional scaling of svg in IE.

Creating an Icon component

The hack is best added to (and eventually removed from) an existing icon component’s implementation.

If you’re generating and inlining an SVG spritemap, you will need to extract the height and width (usually from viewBox) of each of your icons during the build step. If you’re already using the gulp-svgstore plugin, it supports extracting metadata.

Those dimensions need to be set on the canvas element to produce the correct aspect ratio for a given icon.

Example React component (built with webpack):

import iconData from './lib/icons-data.json';
import React from 'react';
import './index.css';

class Icon extends React.Component {
  render() {
    const props = this.props;
    const height = iconData[props.name.height];
    const width = iconData[props.name.width];

    // React doesn't support namespaced attributes, so we have to set the
    // 'use' tag with innerHTML
    const useTag = `<use fill="currentcolor"
                      xlink:href="#icon-${props.name}">
                    </use>`;

    return (
      <span className="Icon">
        <canvas className="Icon-canvas"
          height={height}
          width={width}
        />
        <svg className="Icon-svg"
          dangerouslySetInnerHTML={{__html: useTag}}
          key={props.name}
        />
      </span>
    );
  }
}

export default Icon;

When I introduced this hack to a code base at Twitter, it had no impact on the the rest of the team or the rest of the code base – one of the many benefits of a component-based UI.




an

Redux modules and code-splitting

Twitter Lite uses Redux for state management and relies on code-splitting. However, Redux’s default API is not designed for applications that are incrementally-loaded during a user session.

This post describes how I added support for incrementally loading the Redux modules in Twitter Lite. It’s relatively straight-forward and proven in production over several years.

Redux modules

Redux modules comprise of a reducer, actions, action creators, and selectors. Organizing redux code into self-contained modules makes it possible to create APIs that don’t involve directly referencing the internal state of a reducer – this makes refactoring and testing a lot easier. (More about the concept of redux modules.)

Here’s an example of a small “redux module”.

// data/notifications/index.js

const initialState = [];
let notificationId = 0;

const createActionName = name => `app/notifications/${name}`;

// reducer
export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case ADD_NOTIFICATION:
      return [...state, { ...action.payload, id: notificationId += 1 }];
    case REMOVE_NOTIFICATION:
      return state.slice(1);
    default:
      return state;
  }
}

// selectors
export const selectAllNotifications = state => state.notifications;
export const selectNextNotification = state => state.notifications[0];

// actions
export const ADD_NOTIFICATION = createActionName(ADD_NOTIFICATION);
export const REMOVE_NOTIFICATION = createActionName(REMOVE_NOTIFICATION);

// action creators
export const addNotification = payload => ({ payload, type: ADD_NOTIFICATION });
export const removeNotification = () => ({ type: REMOVE_NOTIFICATION });

This module can be used to add and select notifications. Here’s an example of how it can be used to provide props to a React component.

// components/NotificationView/connect.js

import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { removeNotification, selectNextNotification } from '../../data/notifications';

const mapStateToProps = createStructuredSelector({
  nextNotification: selectNextNotification
});
const mapDispatchToProps = { removeNotification };

export default connect(mapStateToProps, mapDispatchToProps);
// components/NotificationView/index.js

import connect from './connect';
export class NotificationView extends React.Component { /*...*/ }
export default connect(NotificationView);

This allows you to import specific modules that are responsible for modifying and querying specific parts of the overall state. This can be very useful when relying on code-splitting.

However, problems with this approach are evident once it comes to adding the reducer to a Redux store.

// data/createStore.js

import { combineReducers, createStore } from 'redux';
Import notifications from './notifications';

const initialState = /* from local storage or server */

const reducer = combineReducers({ notifications });
const store = createStore(reducer, initialState);

export default store;

You’ll notice that the notifications namespace is defined at the time the store is created, and not by the Redux module that defines the reducer. If the “notifications” reducer name is changed in createStore, all the selectors in the “notifications” Redux module no longer work. Worse, every Redux module needs to be imported in the createStore file before it can be added to the store’s reducer. This doesn’t scale and isn’t good for large apps that rely on code-splitting to incrementally load modules. A large app could have dozens of Redux modules, many of which are only used by a few components and unnecessary for initial render.

Both of these issues can be avoided by introducing a Redux reducer registry.

Redux reducer registry

The reducer registry enables Redux reducers to be added to the store’s reducer after the store has been created. This allows Redux modules to be loaded on-demand, without requiring all Redux modules to be bundled in the main chunk for the store to correctly initialize.

// data/reducerRegistry.js

export class ReducerRegistry {
  constructor() {
    this._emitChange = null;
    this._reducers = {};
  }

  getReducers() {
    return { ...this._reducers };
  }

  register(name, reducer) {
    this._reducers = { ...this._reducers, [name]: reducer };
    if (this._emitChange) {
      this._emitChange(this.getReducers());
    }
  }

  setChangeListener(listener) {
    this._emitChange = listener;
  }
}

const reducerRegistry = new ReducerRegistry();
export default reducerRegistry;

Each Redux module can now register itself and define its own reducer name.

// data/notifications/index.js

import reducerRegistry from '../reducerRegistry';

const initialState = [];
let notificationId = 0;

const reducerName = 'notifications';

const createActionName = name => `app/${reducerName}/${name}`;

// reducer
export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case ADD_NOTIFICATION:
      return [...state, { ...action.payload, id: notificationId += 1 }];
    case REMOVE_NOTIFICATION:
      return state.slice(1);
    default:
      return state;
  }
}

reducerRegistry.register(reducerName, reducer);

// selectors
export const selectAllNotifications = state => state[reducerName];
export const selectNextNotification = state => state[reducerName][0];

// actions
export const ADD_NOTIFICATION = createActionName(ADD_NOTIFICATION);
export const REMOVE_NOTIFICATION = createActionName(REMOVE_NOTIFICATION);

// action creators
export const addNotification = payload => ({ payload, type: ADD_NOTIFICATION });
export const removeNotification = () => ({ type: REMOVE_NOTIFICATION });

Next, we need to replace the store’s combined reducer whenever a new reducer is registered (e.g., after loading an on-demand chunk). This is complicated slightly by the need to preserve initial state that may have been created by reducers that aren’t yet loaded on the client. By default, once an action is dispatched, Redux will throw away state that is not tied to a known reducer. To avoid that, reducer stubs are created to preserve the state.

// data/createStore.js

import { combineReducers, createStore } from 'redux';
import reducerRegistry from './reducerRegistry';

const initialState = /* from local storage or server */

// Preserve initial state for not-yet-loaded reducers
const combine = (reducers) => {
  const reducerNames = Object.keys(reducers);
  Object.keys(initialState).forEach(item => {
    if (reducerNames.indexOf(item) === -1) {
      reducers[item] = (state = null) => state;
    }
  });
  return combineReducers(reducers);
};

const reducer = combine(reducerRegistry.getReducers());
const store = createStore(reducer, initialState);

// Replace the store's reducer whenever a new reducer is registered.
reducerRegistry.setChangeListener(reducers => {
  store.replaceReducer(combine(reducers));
});

export default store;

Managing the Redux store’s reducer with a registry should help you better code-split your application and modularize your state management.




an

Coronavirus | Maharashtra adds 1,089 new cases; Mumbai’s death toll stands at 462

Of the 1,089 new cases, Mumbai accounted for 748, with a cumulative tally of 12,142. With 75 new cases, Pune district’s tally has risen to 2,537.




an

Migrant workers | Maharashtra train accident victims were battling hunger

The previous night, they had called up relatives in Madhya Pradesh to say they were in a helpless state




an

Bihar government to do random testing of migrants on arrival

TrueNat machines will be used for the first time in the State for virus screening




an

Take back changes in labour laws: Priyanka

‘U.P. government crushing their rights’




an

PMC Bank fraud case: Rakesh Wadhawan denied interim bail

HDIL promoter is lodged in Arthur Road Central Jail