ac

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




ac

Correction: Role of polysilicon in poly-Si/SiOx passivating contacts for high-efficiency silicon solar cells

RSC Adv., 2020, 10,17571-17571
DOI: 10.1039/D0RA90049D, Correction
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
HyunJung Park, Soohyun Bae, Se Jin Park, Ji Yeon Hyun, Chang Hyun Lee, Dongjin Choi, Dongkyun Kang, Hyebin Han, Yoonmook Kang, Hae-Seok Lee, Donghwan Kim
The content of this RSS Feed (c) The Royal Society of Chemistry




ac

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




ac

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




ac

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




ac

Work function modification of PEDOT:PSS by mixing with barium acetylacetonate

RSC Adv., 2020, 10,17673-17680
DOI: 10.1039/D0RA02575E, Paper
Open Access
K. L. Woon, W. S. Wong, N. Chanlek, H. Nakajima, S. Tunmee, V. S. Lee, A. Ariffin, P. Songsiriritthigul
Modification of poly(3,4-ethylenedioxythiophene)polystyrene sulfonate as electron injection layer.
The content of this RSS Feed (c) The Royal Society of Chemistry




ac

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




ac

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




ac

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




ac

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




ac

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




ac

Computational study on the polymerization reaction of D-aminopeptidase for the synthesis of D-peptides

RSC Adv., 2020, 10,17582-17592
DOI: 10.1039/D0RA01138J, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Joan Gimenez-Dejoz, Kousuke Tsuchiya, Ayaka Tateishi, Yoko Motoda, Takanori Kigawa, Yasuhisa Asano, Keiji Numata
We studied the molecular mechanism of D-aminopeptidase for the synthesis of polypeptides incorporating D-amino acids.
The content of this RSS Feed (c) The Royal Society of Chemistry




ac

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




ac

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




ac

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




ac

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




ac

Facile synthesis of a direct Z-scheme BiOCl–phosphotungstic acid heterojunction for the improved photodegradation of tetracycline

RSC Adv., 2020, 10,17369-17376
DOI: 10.1039/D0RA02396E, Paper
Open Access
Haijuan Tong, Bingfang Shi, Shulin Zhao
A one-step hydrothermal approach for synthesizing BiOCl–phosphotungstic acid (BiOCl–HPW) heterojunctions is proposed. The prepared BiOCl–HPW heterojunction exhibited good stability and photocatalytic activity.
The content of this RSS Feed (c) The Royal Society of Chemistry




ac

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




ac

Ladybird macro photographs

This morning hundreds of ladybirds were flying through the air and massing on the white walls of the house. I managed to get a few clear macro photographs.

The sun was shining and the ladybirds seemed to be attracted to anything white. I stuck a white T-shirt on and headed outside. Pretty soon I was covered in them and could pluck them from my shirt to get some close ups using my little Canon IXUS 60.

At some point a ladybird took off just before I tried to photograph it and I decided I’d try to capture that moment. A few minutes later I’d worked out that I could prompt one of the insects to walk up my finger like the stem of a flower, that they’d take off when they reached the tip, and that they took up a distinct posture just before their wing-case shot open.

The speed at which they prepare to take off, open their wings, and fly away is so quick that I just had to take the shot as soon as I saw a ladybird get into the “take-off position” and hope that I reacted fast enough to get a picture of the open wing-case.




ac

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




ac

CSS image replacement. One more time.

An accessible image replacement method using pseudo-elements and generated-content. This method works with images and/or CSS off, with semi-transparent images, doesn’t hide text from screen-readers or search engines, and provides fallback for IE 6 and IE 7.

Known support: Firefox 1.5+, Safari 3+, Chrome 3+, Opera 9+, IE 8+

What’s wrong with current methods?

The two most widely used image replacement techniques are the Gilder/Levin Method and the Phark Method. Both have different flaws.

The Gilder/Levin Method requires the addition of presentational HTML (an empty span) and doesn’t work with transparent images as the default text shows through. The Phark Method uses a negative text-indent to hide the text and so it is not visible when CSS is on and images are off.

Resurrecting the NIR method

Using pseudo-elements and generated-content as an image replacement technique isn’t a new idea. It was proposed and demonstrated by Paul Nash back in 2006. This is the Nash Image Replacement method.

<h1 class="nir">[content]</h1>
.nir {
   height: 100px; /* height of replacement image */
   padding: 0;
   margin: 0;
   overflow: hidden;
}

.nir:before {
   content: url(image.gif);
   display: block;
}

The height value is equal to that of the replacement image. Setting overflow:hidden ensures that the original content is not visible on screen when the image is loaded. The replacement image is inserted as generated content in the :before pseudo-element which is set to behave like a block element in order to push the element’s original content down.

What about IE 6 and IE 7?

Neither browser supports :before; if you need to support them you’ll have to rely on the Phark method. This can be done using conditional comments or safe IE6/7 hacks to serve alternative styles to legacy versions of IE .

<!--[if lte IE 7]>
<style>
.nir {
   height: 100px;
   padding: 0;
   margin: 0;
   overflow: hidden;
   text-indent: -9000px;
   background: url(image.gif) no-repeat 0 0;
}
</style>
<![endif]-->

Using the NIR method allows you to keep your HTML semantic and deliver improved accessibility to users of modern browsers. The Phark Method can then be served to IE 6 and IE 7.

Improving the NIR method

The first problem with NIR is that if images are disabled all browsers leave whitespace above the element’s content. Opera 10.5 even displays the text string “image”! If the height of the element is small enough this whitespace causes the element’s content to overflow and be partially or completely hidden when images are disabled.

Another consideration is what happens if an image doesn’t exist or fails to load. Safari and Chrome will display a “missing image” icon that cannot be removed. Once again, this can cause the element’s content to overflow and become partially or completely hidden to users.

A more robust version of the NIR method is the following modification:

.nir {
   height: 100px; /* height of replacement image */
   width: 400px; /* width of replacement image */
   padding: 0;
   margin: 0;
   overflow: hidden;
}

.nir:before {
   content: url(image.gif);
   display: inline-block;
   font-size: 0;
   line-height: 0;
}

Setting font-size and line-height to 0 avoids the whitespace problems in all browsers. Setting the element’s width equal to that of the replacement image and getting the pseudo-element to act as an inline-block helps minimise the problems in webkit browsers should an image fail to load.

Ideally browsers would avoid displaying anything in a pseudo-element when its generated-content image fails to load. If that were the case, the original NIR method would be all that is needed.

What about using sprites?

One of the most common uses of image replacement is for navigation. This often involves using a large sprite with :hover and :active states as a background image. It turns out that using sprites is not a problem for modern browsers. When using the modified-NIR method the sprite is included as a generated-content image that is positioned using negative margins.

This is an example that rebuilds the right-hand category navigation from Web Designer Wall using a sprite and the modified-NIR method.

<ul id="nav">
  <li id="nav-item-1"><a href="#non">Tutorials</a></li>
  <li id="nav-item-2"><a href="#non">Trends</a></li>
  <li id="nav-item-3"><a href="#non">General</a></li>
</ul>
/* modified-NIR */

#nav a {
  display: block;
  width: 225px;
  height: 46px;
  overflow: hidden;
}

#nav a:before {
   content:url(sprite.png);
   display:-moz-inline-box; /* for Firefox 1.5 & 2 */
   display:inline-block;
   font-size:0;
   line-height:0;
}

/* repositioning the sprite */

#nav-item-1 a:hover:before,
#nav-item-1 a:focus:before,
#nav-item-1 a:active:before {margin:-46px 0 0;}

#nav-item-2 a:before        {margin:-92px 0 0;}
#nav-item-2 a:hover:before,
#nav-item-2 a:focus:before,
#nav-item-2 a:active:before {margin:-138px 0 0;}

#nav-item-3 a:before        {margin:-184px 0 0;}
#nav-item-3 a:hover:before,
#nav-item-3 a:focus:before,
#nav-item-3 a:active:before {margin:-230px 0 0;}

/* :hover hack for IE8 if no a:hover styles declared */
#nav a:hover {cursor:pointer;}

For some reason IE8 refuses to reposition the image when the mouse is over the link unless a style is declared for a:hover. In most cases you will have declared a:hover styles for the basic links on your webpage, and this is enough. But it is worth being aware of this IE8 behaviour.

The addition of display:-moz-inline-box; is required to reposition the sprite in versions of Firefox prior to Firefox 3.0. They are very rare browsers but I’ve included it in case that level of legacy support is needed.

If you want image replacement in IE 6 and IE 7 the following additional styles can be served to those browsers using conditional comments.

/* Phark IR method */

#nav a {
   text-indent: -9000px;
   background: url(sprite.png) no-repeat;
}

/* repositioning the sprite */

#nav-item-1 a:hover,
#nav-item-1 a:active { background-position: 0 -46px; }

#nav-item-2 a        { background-position: 0 -92px; }
#nav-item-2 a:hover,
#nav-item-2 a:hover  { background-position: 0 -138px; }

#nav-item-3 a        { background-position: 0 -184px; }
#nav-item-3 a:hover,
#nav-item-3 a:active { background-position: 0 -230px; }

/* hack for IE6 */
#nav a:hover { margin: 0; }

The changes are fairly simple. But IE 6 applies the margins declared for a:hover:before to a:hover and so they need to be reset in the styles served to IE 6.

See the modified-NIR (using sprites) demo.




ac

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.




ac

CSS background image hacks

Emulating background image crop, background image opacity, background transforms, and improved background positioning. A few hacks relying on CSS pseudo-elements to emulate features unavailable or not yet widely supported by modern browsers.

Demos: Example CSS background image hacks

Pseudo-element hacks can fill some gaps in existing browser support for CSS features, without resorting to presentational HTML. In some cases, they even make it possible to emulate things that are not currently part of any W3C working draft, like background transforms and background image opacity.

Most of the hacks in this article tie in with the pseudo-element hack described in an earlier article – Multiple Backgrounds and Borders with CSS 2.1. That article already describes how to emulate multiple background support and its demo page shows several other uses of the basic principle. This article presents a few of those effects and applications in greater detail.

Emulating background-crop

Known support: Firefox 3.5+, Opera 10+, Safari 4+, Chrome 4+, IE 8+

Demo: Pseudo background-crop

Background image cropping can be emulated in modern browsers using only CSS 2.1. The principle behind a pseudo background-crop is to apply a background-image to a pseudo-element rather than the element itself. One example would be to crop an image to display in the background. Another would be to crop an image sprite to display icons alongside text in links.

In several cases, using pseudo-elements may have advantages over existing, alternative techniques because it combines their strengths and avoids some of their weaknesses.

Google, Facebook, and Twitter all make use of empty DOM elements to crop dense sprites and display icons next to certain links in their interfaces. The alternative is not to use empty elements but be forced into using multiple images and/or to design sub-optimal image sprites that have their component images spaced out.

Pseudo-elements can be used in much the same way as empty DOM elements. This simultaneously eliminates the need for presentational HTML and doesn’t depend so heavily on an image sprite’s design. Using pseudo-elements for this purpose does have its own drawback – a lack of support in legacy browsers like IE6 and IE7. However, the technique will progressively enhance capable browsers while leaving a perfectly usable experience for incapable browsers.

Example code: cropping a sprite

This example shows how to crop icons that are part of a dense image sprite that uses a 16px × 16px grid. It uses a simple list and specifies a class for each type of action.

<ul class="actions">
  <li class="save"><a href="#">Save</a></li>
  <li class="delete"><a href="#">Delete</a></li>
  <li class="share"><a href="#">Share</a></li>
  <li class="comment"><a href="#">Comment</a></li>
</ul>

Styling can be applied to present this list in whatever way is needed. From that base, a pseudo-element can be created and then treated as you would an empty, inline DOM element (e.g. <span>).

In this case, the :before pseudo-element is used and sized to match the sprite’s grid unit. It could be sized to whatever dimensions are required to match a section of the sprite that needs to be cropped.

.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 -16px; }
.delete a:before { background-position: 0 -32px; }
.share a:before { background-position: 0 -48px; }
.comment a:before { background-position: 0 -64px; }

Providing hover, focus, active, and “saved” states is just a case of declaring the correct background position in each case.

.save a:hover:before,
.save a:focus:before,
.save a:active:before {
  background-position: -16px -16px;
}

.saved a:before {
  background-position: -32px -16px;
}

Future alternatives

In the future, there will be other alternatives. Firefox 3.6 added -moz-image-rect to allow background images to be cropped. But this is not supported by other browsers and looks likely to be replaced by an alternative proposal (to use fragment identifiers) that is part of the CSS Image Values Module Level 3 specification. As far as I know, no stable release of any modern browser supports the use of fragment identifiers with bitmap images at the time of writing.

Emulating background-transform

Known support: Firefox 3.6+, Opera 10.5+, Safari 4+, Chrome 4+, IE 9+

Demo: Pseudo background-transform

Combining pseudo-elements and transforms makes it possible to emulate background transforms. A pseudo background-transform can be used to rotate, scale, and skew background images and sprites. There is no proposal for background-image transforms, so a pseudo-element hack is one way to emulate it.

Example: rotating a background image

The example of cropping sprites can be further developed by reducing the number of different images used in the sprite. Rather than applying transforms to images in a graphics package, they can be applied in the CSS.

The code to do this is relatively simple and might look something like:

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

.accordion.open a:before {
  transform: rotate(90deg);
}

To apply a transform to a more conventional background image (e.g., a large graphic sitting behind some content that doesn’t affect the positioning of other components) requires use of the positioning technique detailed in the article Multiple Backgrounds and Borders with CSS 2.1.

It involves setting the background image on a pseudo-element which is then positioned behind the content layer of an element using absolute positioning and z-index.

Example: mirroring a background image

There are instances when mirroring a background image might be desired. The approach is similar to that for rotating an image, but this time uses transform:scale().

Producing an exact mirror of an element or pseudo-element can be done using transform:scaleX(-1), transform:scaleY(-1), and transform:scale(-1,-1) to mirror along the x-axis, y-axis, and both axes, respectively.

The following code is an example of how a pseudo background-transform might be used for pagination links. A pseudo-element displays a single image (or region of a sprite) and is then mirrored. The image’s appearance is such that a rotation cannot produce the desired counterpart. Only a scale operation can do it.

.prev a:before,
.next a:before {
  content: "";
  float: left;
  width: 16px;
  height: 16px;
  margin: 0 5px 0 0;
  background: url(sprite.png) no-repeat 0 0;
}

.next a:before {
  float: right;
  margin: 0 0 0 5px;
  transform: scaleX(-1);
}

There is no support for this in IE 8. Even if you’re a fan of using IE filters to work around some missing CSS support, they won’t work on pseudo-elements.

Future alternatives

There don’t seem to be any future alternatives in any CSS working draft. For the moment, it looks like pseudo-element hacks will be needed to emulate effects like background transforms and background perspective without resorting to presentational HTML.

Emulating background-position

Known support: Firefox 3.5+, Opera 10+, Safari 4+, Chrome 4+, IE 8+

Demo: Pseudo background-position

The CSS 2.1 specification limits the values of background-position to offsets from the left and top sides. It’s possible to emulate positioning a background image from the right and bottom sides by applying the background image to a pseudo-element and using it as an additional background layer.

This hack is easily combined with the other hacks in this article. More details on the pseudo background-position hack can be found in the article on Multiple Backgrounds and Borders with CSS 2.1.

Example code

In this example, a pseudo-element is created and placed behind the element’s content layer. The background image is 500px × 300px and declared for the pseudo-element, which is also given dimensions that match those of the image. Since the pseudo-element is absolutely positioned, it can be positioned from the bottom and right of the element using offsets.

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

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

Future alternatives

There is a part of the CSS Backgrounds and Borders module working draft that describes an improvement to the background-position property to allow positions to be set from any side. At the moment, Opera 11 is the only stable release of a browser that has implemented it.

Emulating background-opacity

Known support: Firefox 3.5+, Opera 10+, Safari 4+, Chrome 4+, IE 9+

Demo: Pseudo background-opacity

Changing the opacity of a pseudo-background is as simple as modifying the value of the opacity property. There is no IE 8 support for opacity and IE filters will not work on pseudo-elements.

Example code

This example code shows a pseudo-element being created and positioned behind the rest of the element’s content so as not to interfere with it. The pseudo-element is then sized to fit the element using offsets (but could be offset by other values or given an explicit size), given a background image, and has its opacity changed.

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

#content:before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: url(image.jpg);
  opacity: 0.7;
}

Notes

For now, and as far as I am aware, using CSS 2.1 pseudo-elements is the only widely supported (and backwards compatible) way to emulate background image crop, background transform, background opacity, and improved background positioning with semantic HTML.

Even when alternatives in CSS working drafts (e.g., the improved background-position and use of fragment identifiers) are widely implemented, pseudo-element background-image hacks will still have the advantage of letting you use other CSS properties like opacity, border-radius, border-image, box-shadow, transforms, etc., which may prove useful in certain situations. It can’t hurt to be aware of these options.

It’s worth mentioning that although you can only generate 2 pseudo-elements from a DOM element, in many cases you can easily use descendant elements to provide more pseudo-elements to play with. This idea was used to help create the rotated example on the CSS drop-shadows demo page and several of the CSS3 examples at the bottom of the pure CSS speech bubbles demo page.

Thanks to Mathias Bynens for reading and giving feedback on a draft of this article.




ac

A new micro clearfix hack

The clearfix hack is a popular way to contain floats without resorting to using presentational markup. This article presents an update to the clearfix method that further reduces the amount of CSS required.

Demo: Micro clearfix hack

Known support: Firefox 3.5+, Safari 4+, Chrome, Opera 9+, IE 6+

The “micro clearfix” method is suitable for modern browsers and builds upon Thierry Koblentz’s “clearfix reloaded”, which introduced the use of both the :before and :after pseudo-elements.

Here is the updated code (I’ve used a shorter class name too):

/**
 * For modern browsers
 * 1. The space content is one way to avoid an Opera bug when the
 *    contenteditable attribute is included anywhere else in the document.
 *    Otherwise it causes space to appear at the top and bottom of elements
 *    that are clearfixed.
 * 2. The use of `table` rather than `block` is only necessary if using
 *    `:before` to contain the top-margins of child elements.
 */
.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.cf:after {
    clear: both;
}

/**
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
    *zoom: 1;
}

This “micro clearfix” generates pseudo-elements and sets their display to table. This creates an anonymous table-cell and a new block formatting context that means the :before pseudo-element prevents top-margin collapse. The :after pseudo-element is used to clear the floats. As a result, there is no need to hide any generated content and the total amount of code needed is reduced.

Including the :before selector is not necessary to clear the floats, but it prevents top-margins from collapsing in modern browsers. This has two benefits:

  • It ensures visual consistency with other float containment techniques that create a new block formatting context, e.g., overflow:hidden
  • It ensures visual consistency with IE 6/7 when zoom:1 is applied.

N.B.: There are circumstances in which IE 6/7 will not contain the bottom margins of floats within a new block formatting context. Further details can be found here: Better float containment in IE using CSS expressions.

The use of content:" " (note the space in the content string) avoids an Opera bug that creates space around clearfixed elements if the contenteditable attribute is also present somewhere in the HTML. Thanks to Sergio Cerrutti for spotting this fix. An alternative fix is to use font:0/0 a.

Legacy Firefox

Firefox < 3.5 will benefit from using Thierry’s method with the addition of visibility:hidden to hide the inserted character. This is because legacy versions of Firefox need content:"." to avoid extra space appearing between the body and its first child element, in certain circumstances (e.g., jsfiddle.net/necolas/K538S/.)

Alternative float-containment methods that create a new block formatting context, such as applying overflow:hidden or display:inline-block to the container element, will also avoid this behaviour in legacy versions of Firefox.




ac

Better conditional classnames for hack-free CSS

Applying conditional classnames to the html element is a popular way to help target specific versions of IE with CSS fixes. It was first described by Paul Irish and is a feature of the HTML5 Boilerplate. Despite all its benefits, there are still a couple of niggling issues. Here are some hacky variants that side-step those issues.

An article by Paul Irish, Conditional stylesheets vs CSS hacks? Answer: Neither!, first proposed that conditional comments be used on the opening html tag to help target legacy versions of IE with CSS fixes. Since its inclusion in the HTML5 Boilerplate project, contributors have further refined the technique.

However, there are still some niggling issues with the “classic” conditional comments approach, which Mathias Bynens summarized in a recent article on safe CSS hacks.

  1. The Compatibility View icon is displayed in IE8 and IE9 if you are not setting the X-UA-Compatible header in a server config.
  2. The character encoding declaration might not be fully contained within the first 1024 bytes of the HTML document if you need to include several attributes on each version of the opening html tag (e.g. Facebook xmlns junk).

You can read more about the related discussions in issue #286 and issue #378 at the HTML5 Boilerplate GitHub repository.

The “bubble up” conditional comments method

Although not necessarily recommended, it looks like both of these issues can be avoided with a bit of trickery. You can create an uncommented opening html tag upon which any shared attributes (so no class attribute) can be set. The conditional classes are then assigned in a second html tag that appears after the <meta http-equiv="X-UA-Compatible"> tag in the document. The classes will “bubble up” to the uncommented tag.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible"
          content="IE=edge,chrome=1">
    <meta charset="utf-8">
    <!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
    <!--[if IE 7]><html class="no-js ie7"><![endif]-->
    <!--[if IE 8]><html class="no-js ie8"><![endif]-->
    <!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->

    <title>Document</title>
  </head>
  <body>
  </body>
</html>

Fork the Gist

The result is that IE8 and IE9 won’t ignore the <meta http-equiv="X-UA-Compatible"> tag, the Compatibility View icon will not be displayed, and the amount of repeated code is reduced. Obviously, including a second html tag in the head isn’t pretty or valid HTML.

If you’re using a server-side config to set the X-UA-Compatible header (instead of the meta tag), then you can still benefit from the DRYer nature of using two opening html tags and it isn’t necessary to include the conditional comments in the head of the document. However, you might still want to do so if you risk not containing the character encoding declaration within the first 1024 bytes of the document.

<!DOCTYPE html>
<html lang="en">
<!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
<!--[if IE 7]><html class="no-js ie7"><![endif]-->
<!--[if IE 8]><html class="no-js ie8"><![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->
  <head>
    <meta charset="utf-8">
    <title>Document</title>
  </head>
  <body>
  </body>
</html>

Fork the Gist

The “preemptive” conditional comments method

Another method to prevent the Compatibility View icon from showing was found by Julien Wajsberg. It relies on including a conditional comment before the DOCTYPE. Doing this seems to help IE recognise the <meta http-equiv="X-UA-Compatible"> tag. This method isn’t as DRY and doesn’t have the character encoding declaration as high up in the document, but it also doesn’t use 2 opening html elements.

<!--[if IE]><![endif]-->
<!DOCTYPE html>
<!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
<!--[if IE 7]><html class="no-js ie7"><![endif]-->
<!--[if IE 8]><html class="no-js ie8"><![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta charset="utf-8">
    <title>Document</title>
  </head>
  <body>
  </body>
</html>

Fork the Gist

While it’s interesting to explore these possibilities, the “classic” method is still generally the most understandable. It doesn’t create invalid HTML, doesn’t risk throwing IE into quirks mode, and you won’t have a problem with the Compatibility View icon if you use a server-side config.

If you find any other approaches, or problems with those posted here, please leave a comment but also consider adding what you’ve found to the relevant issues in the HTML5 Boilerplate GitHub repository.

Thanks to Paul Irish for feedback and suggestions.




ac

Mac OS X bootable backup drive with rsync

I’ve started using a backup strategy based on that originally described by Jamie Zawinski and subsequently covered in Jeff Atwood’s What’s your backup strategy? article. It works by incrementally backing up your data to a bootable clone of your computer’s internal drive, in order to replace the internal drive when it fails.

This script is maintained in my dotfiles repo. Please report problems or improvements in the issue tracker.

This post is mainly to document – for myself as much as anything – the process I went through in order to implement an incremental backup strategy in OS X 10.6+. Use at your own risk. Feel free to suggest improvements if you know of any.

Formatting and partitioning the drive

With your backup drive in its enclosure, connect the drive to your Mac and open the Disk Utility application.

  1. Click on the disk’s name. This should bring up a “Partition” tab in the right panel.
  2. Click on the “Partition” tab.
  3. Under “Volume scheme” select the number of partitions you need. Probably “1 partition” if it is to match your internal disk.
  4. Under “Name” enter the volume name you want to use, e.g., “Backup”.
  5. Under “Format” select “Mac OS X Extended (Journaled)”, which is necessary if the disk is to be bootable.
  6. Click “Options” and check that “GUID Partition Table” is selected.
  7. Click “Apply”.

This will format and partition the disk. The partition(s) should now show up in the Finder and on the Desktop.

Enable ownership permissions

The new partition needs permissions to be enabled to avoid chown errors when using rsync. To do this, select the partition and view its information page (using “Get Info” or Command+I). Expand the “Ownership & Permissions” section and uncheck “Ignore ownership on this volume”

Backup script

The backup script uses rsync – a fast and versatile file copying tool – to manage the copying and moving of data between volumes. You need to install rsync 3 (this is easily done using Homebrew: brew install https://raw.github.com/Homebrew/homebrew-dupes/master/rsync.rb). Rsync offers a wide variety of options and only copies the differences between the source files and the existing files in the destination, making it ideal for incremental backups. You can find out more about rsync in the rsync documentation

The following is the contents of a script I’ve named backup. I’m using it to backup all of the data on my internal disk, with a specified set of exceptions contained within a file called .backupignore.

#!/bin/bash

# Disc backup script
# Requires rsync 3

# Ask for the administrator password upfront
sudo -v

# IMPORTANT: Make sure you update the `DST` variable to match the name of the
# destination backup drive

DST="/Volumes/Macintosh HD/"
SRC="/"
EXCLUDE="$HOME/.backupignore"

PROG=$0

# --acls                   update the destination ACLs to be the same as the source ACLs
# --archive                turn on archive mode (recursive copy + retain attributes)
# --delete                 delete any files that have been deleted locally
# --delete-excluded        delete any files (on DST) that are part of the list of excluded files
# --exclude-from           reference a list of files to exclude
# --hard-links             preserve hard-links
# --one-file-system        don't cross device boundaries (ignore mounted volumes)
# --sparse                 handle sparse files efficiently
# --verbose                increase verbosity
# --xattrs                 update the remote extended attributes to be the same as the local ones

if [ ! -r "$SRC" ]; then
    logger -t $PROG "Source $SRC not readable - Cannot start the sync process"
    exit;
fi

if [ ! -w "$DST" ]; then
    logger -t $PROG "Destination $DST not writeable - Cannot start the sync process"
    exit;
fi

logger -t $PROG "Start rsync"

sudo rsync --acls 
           --archive 
           --delete 
           --delete-excluded 
           --exclude-from=$EXCLUDE 
           --hard-links 
           --one-file-system 
           --sparse 
           --verbose 
           --xattrs 
           "$SRC" "$DST"

logger -t $PROG "End rsync"

# Make the backup bootable
sudo bless -folder "$DST"/System/Library/CoreServices

exit 0

Adapted from the rsync script at Automated OSX backups with launchd and rsync

This is the contents of the .backupignore file.

.Spotlight-*/
.Trashes
/afs/*
/automount/*
/cores/*
/dev/*
/Network/*
/private/tmp/*
/private/var/run/*
/private/var/spool/postfix/*
/private/var/vm/*
/Previous Systems.localized
/tmp/*
/Volumes/*
*/.Trash

Adapted from the excludes file at Automated OSX backups with launchd and rsync

Every time the script runs, messages will be written to the system log.

Check that the source (SRC) and destination (DST) paths in the script are correct and match the volume name that you chose when partitioning the disk. Wrapping the $SRC and $DST variables in double quotes ensures that the script will work even if your volume names contain spaces (e.g. “Macintosh Backup”).

The command option --exclude-from tells the script where to find the file containing the exclude patterns. Make sure you either have .backupignore in the home directory or that you update this part of the command to reference the full path of the excludes file.

Running the backup script

You can run the script from the command line, or make it executable from the Finder or the Desktop:

  1. Type the following into the command line to ensure that you have permission to execute the script:

    chmod +x /path/to/rsync_backup.sh
    
  2. Remove the .sh extension from the script.

  3. Create an alias of the script and move it to the Desktop.
  4. Double click the icon to run the backup script.

It’s important to run the script regularly in order to keep the backup in sync with your internal disk. If you have a desktop computer, or you never turn off your laptop, you can automate the running of the script by setting up a cron job.

Checking the disk is bootable

Once you’ve run the backup script, you should test that the backup disk is bootable. To do this, restart your computer and hold down the Alt/Option key. Your backup disk should be presented, with the volume name you chose, as a bootable disk.

When I first booted my backup, the terminal displayed the following line:

dyld: shared cached file was build against a different libSystem.dylib, ignoring cache

According to this article, the fix for this is to update the cache by entering the following into the terminal:

sudo update_dyld_shared_cache -force

That should be everything you need to start implementing an incremental backup strategy when using OS X.




ac

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




ac

“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.




ac

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




ac

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.




ac

Making SVG icon libraries for React apps

Using SVG is currently the best way to create icon libraries for apps. Icons built with SVG are scalable and adjustable, but also discrete, which allows them to be incrementally loaded and updated. In contrast, icons built as fonts cannot be incrementally loaded or updated. This alone makes SVG icons the better choice for high-performance apps that rely on code-splitting and incremental deploys.

This post describes how to make a package of React components from a library of SVG icons. Although I’m focusing on React, making any other type of package is also possible. At Twitter I used the approach described here to publish the company’s SVG icon library in several different formats: optimized SVGs, plain JavaScript modules, React DOM components, and React Native components.

Using the icons

The end result is a JavaScript package that can be installed and used like any other JavaScript package.

yarnpkg add @acme/react-icons

Each icon is available as an individually exported React component.

import IconCamera from '@acme/react-icons/camera';

This allows your module bundler to package only the icons that are needed, and icons can be efficiently split across chunks when using code-splitting. This is a significant advantage over icon libraries that require fonts and bundle all icons into a single component.

// entire icon library is bundled with your app
import Icon from '@acme/react-icons';
const IconCamera = <Icon name='camera' />;

Each icon is straightforward to customize (e.g., color and dimensions) on a per-use basis.

import IconCamera from '@twitter/react-icons/camera';
const Icon = (
  <IconCamera
    style={{ color: 'white', height: '2em' }}
  />
);

Although the icons render to SVG, this is an implementation detail that isn’t exposed to users of the components.

Creating components

Each React component renders an inline SVG, using path and dimensions data extracted from the SVG source files. A helper function called createIconComponent means that only a few lines of boilerplate are needed to create a component from SVG data.

import createIconComponent from './utils/createIconComponent';
import React from 'react';
const IconCamera = createIconComponent({
  content: <g><path d='...'></g>,
  height: 24,
  width: 24
});
IconCamera.displayName = 'IconCamera';
export default IconCamera;

This is an example of what the createIconComponent function looks like when building components for a web app like Twitter Lite, which is built with React Native for Web.

// createIconComponent.js
import { createElement, StyleSheet } from 'react-native-web';
import React from 'react';

const createIconComponent = ({ content, height, width }) =>
  (initialProps) => {
    const props = {
      ...initialProps,
      style: StyleSheet.compose(styles.root, initialProps.style),
      viewBox: `0 0 ${width} ${height}`
    };

    return createElement('svg', props, content);
  };

const styles = StyleSheet.create({
  root: {
    display: 'inline-block',
    fill: 'currentcolor',
    height: '1.25em',
    maxWidth: '100%',
    position: 'relative',
    userSelect: 'none',
    textAlignVertical: 'text-bottom'
  }
});

Setting the fill style to currentcolor allows you to control the color of the SVG using the color style property instead.

All that’s left is to use scripts to process the SVGs and generate each React component.

Creating icon packages

A complete example of one way to do this can be found in the icon-builder-example repository on GitHub.

The project structure of the example tool looks like this.

.
├── README.md
├── package.json
├── scripts/
    ├── build.js
    ├── createReactPackage.js
    └── svgOptimize.js
└── src/
    ├── alerts.svg
    ├── camera.svg
    ├── circle.svg
    └── ...

The build script uses SVGO to optimize the SVGs, extract SVG path data, and extract metadata. The example packager for React then uses templates to create a package.json and the React icon components shown earlier.

import createIconComponent from './utils/createIconComponent';
import React from 'react';
const ${componentName} = createIconComponent({
  height: ${height},
  width: ${width},
  content: <g>${paths}</g>
});
${componentName}.displayName = '${componentName}';
export default ${componentName};

Additional packagers can be included to build other package types from the same SVG source. When the underlying icon library changes, it only takes a couple of commands to rebuild hundreds of icons and publish new versions of each package.




ac

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




ac

AMU academic session from Aug.

1,300 students of the varsity leave for home by special train




ac

Take back changes in labour laws: Priyanka

‘U.P. government crushing their rights’




ac

PNB scam: HC rejects bail plea of accused who tested positive for COVID-19

Court says Hemant Bhatt needs to be treated at a govt. hospital




ac

Crime Branch busts cigarette, tobacco smuggling racket

Material brought illegally in vehicles that had permission to carry fruits and vegetables




ac

Army will not be called into Mumbai, assures Uddhav Thackeray

In his address, CM says lockdown cannot go on forever




ac

Coronavirus | Assam rights activist held for social media post

Rupa Rani Bhuyan, assistant professor of Mangaldoi College, was held for “misbehaving” with the police and “obstructing” them from investigating cases against her




ac

Punjab Cabinet nod for non-teaching staff transfer policy

State mulling changes in excise policy, labour laws amid lockdown




ac

Illicit liquor racket busted




ac

The stirring of soul in the workplace [electronic resource] / Alan Briskin

Briskin, Alan, 1954-




ac

Strategisches management für KMU [electronic resource] : unternehmenswachstum durch (r)evolutionäre Unternehmensführung / Gerrit Hamann

Hamann, Gerrit, author




ac

The strategy of execution [electronic resource] : the five-step guide for turning vision into action / Liz Mellon and Simon Carter

Mellon, Elizabeth




ac

Streamlining business requirements [electronic resource] : the XCellR8 approach / Gerrie Caudle

Caudle, Gerrie




ac

Stress less. achieve more [electronic resource] : simple ways to turn pressure into a positive force in your life / Aimee Bernstein

Bernstein, Aimee




ac

The stress test every business needs [electronic resource] : a capital agenda for confidently facing digital disruption, difficult investors, recessions and geopolitical threats / Jeffrey R. Greene, Steve Krouskos, Julie Hood, Harsha Basnayake, William Ca

Greene, Jeffrey R., author




ac

Supplier selection at Kerneos, Inc. [electronic resource] / Chuck Munson ; with Ling Li, Erika Marsillac, and Ted Kosiek

Munson, Chuck, author




ac

Supply chain management talent development [electronic resource] : acquire, develop, and advance processes / Council of Supply Chain Management Professionals

Council of Supply Chain Management Professionals, author




ac

Tail risk killers: how math, indeterminacy, and hubris distort markets [electronic resource] / Jeffrey McGinn, Vineer Bhansali

McGinn, Jeffrey




ac

Tatort Projekt [electronic resource] : Wenn die Wahrheit das Geschäft stört / Jacqueline Irrgang

Irrgang, Jacqueline, 1959- author