123

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <head>
<!-- Fonts to load from fonts.google.com-->
<!-- Saira comes in 9 weights -->
<link href="https://fonts.googleapis.com/css?family=Saira:100,200,300,400,500,600,700,800,900" rel="stylesheet"> 
  
 <!-- Saira also comes in 4 widths -->
<link href="https://fonts.googleapis.com/css?family=Saira|Saira+Condensed|Saira+Extra+Condensed|Saira+Semi+Condensed" rel="stylesheet"> 
  
<!-- These fonts are fairly different from one another -->
<link href="https://fonts.googleapis.com/css?family=Aldrich|Arima+Madurai|Arvo|Henny+Penny|Indie+Flower|Libre+Baskerville|Pirata+One|Poiret+One|Sancreek|Satisfy|Share+Tech+Mono|Smokum|Snowburst+One|Special+Elite" rel="stylesheet"> 
</head>

<H2>Data-driven typographic attributes using D3.js</H2>

<p><small>Below are D3 examples, created using these attribute tags in SVG for various font attributes:
<ul>
<li> Color: <i>fill</i>
<li> Weight: <i>font-weight</i> Ranges from 100-900. Must be supported by specific font available to the page, e.g. fonts.google.com Saira has nine weights, load all nine to use them, see the header.
<li> Oblique: to create variable oblique angles, use skewX() in a group-transformation applied to each text item
<li> Typeface: <i>font-family</i> First, load many typefaces in the header, then apply.
<li> Underline: <i>text-decoration</i> Set to <i>underline</i> to get an underline, but otherwise SVG provides very little control over underline style. Use <i>tspan</i> to limit the scope of the underline (or any other attribute. Note use of invisible characters to make the underline longer than the word. Unfortunately, inconsistent support across browsers.
<li> Width: <i>font-family</i> While there is a width attribute in SVG, get more consistent results by loading a font with many widths (e.g. Saira) and then changing the font to match the desired width. Use a D3 quantile scale instead of the case statement for more effective control. 
<li> Spacing: <i>letter-spacing</i> Tracking - i.e. the space between letters. Note inconsistent browser support - doesn't seem to work in my Firefox.
<li> Baseline: <i>dy</i> A list of dy offsets shift the letters up/down. Text on path could be used instead and is supported in SVG.  
<li> Outline: <i>stroke</i> and <i> stroke-width</i>. While feasible, tricky to use as the stroke widths can make the text hard to read - e.g. the counters (i.e. holes) insted the letters tend to fill in making them blobby, such as the a in Ian and the e in Gem. 
<li> Combos: Any of the above can be combined together to create additional encodings. 
            
          
!
            
              		h2 {
			font-family: "Roboto Slab";
			font-weight: 700;
			color: #222277;
		}
            
          
!
            
              // Some Data, Colors and Fonts:
data = ["Abe","Bev","Cam","Dan","Eve","Fay","Gem","Hui","Ian"];
clrs = ["red","brown","coral","goldenrod","maroon","olive","orchid","tomato","peru","plum","salmon","teal","tan","thistle","indigo","black","lime","aqua"];
fonts = ["Aldrich","Arima Madurai","Henny Penny","Indie Flower","Libre Baskerville","Pirata One","Sancreek","Satisfy","Share Tech Mono","Smokum","Snowburst One","Special+Elite","Arvo"]
    
// Create the SVG canvas:
var svg = d3.select("body").append("svg")
    .attr("width", 500)
    .attr("height", 270);
	
// Color text via fill:  
svg.append("text")
    .attr("x",10).attr("y",15).text("Color:")
svg.selectAll("clrtext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
	  .attr("y",15)
	  .attr("font-family", "Saira")
	  .attr("fill", function(d,i) {return clrs[i];})
	  .text( function(d) {return d;});
  
// Weight via svg font-weight. 
// Uses values from 100-900, depending on the font chosen. 
// See fonts.google.com for sample fonts and weights
// The font Saira has 9 weights 
svg.append("text")
    .attr("x",10).attr("y",35).text("Weight:")
svg.selectAll("boldtext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",35)
  	.attr("font-family", "Saira")
  	.attr("font-weight",function(d,i) {return i*100+100;})
  	.text( function(d) {return d;});

// Oblique angle via svg transform skewX() on a group, then append the text
svg.append("text")
    .attr("x",10).attr("y",55).text("Oblique:")
obliquetext = svg.selectAll("obliquetext").data(data).enter().append("g") 
    .attr("transform", function (d,i) {return "translate(" + (i*40+100) + ",55)" +
                                            " skewX(" + (i*10-40) + ")"; });
  obliquetext.append("text")
	  .attr("font-family", "Saira")
	  .text( function(d) {return d;});	
	
// Caps via javascript toUpperCase() and toLowerCase
// Use <tspan> to apply to subsets of strings
svg.append("text")
    .attr("x",10).attr("y",75).text("Case:")
var casetext = svg.selectAll("casetext").data(data).enter().append("text") 
  .attr("x",function(d,i) {return i*40+100;})
	.attr("y",75)
	.attr("font-family", "Saira");
  casetext.append("tspan")
    .attr("font-variant","small-caps")
  	.text( function(d,i) {return i<5 ? d.substring(0,i).toLowerCase() : 
                                       d.substring(0,i%5).toUpperCase(); })
  casetext.append("tspan")
    .attr( "font-variant",function(d,i) {return i<5 ? "normal" : "small-caps";})
  	.text( function(d,i) {return d.substring(i%5,10).toLowerCase();});
  
// Typeface via font-family:
svg.append("text")
    .attr("x",10).attr("y",95).text("Typeface:")
svg.selectAll("fonttext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",95)
  	.attr("font-family", function(d,i) {return fonts[i];})
  	.text( function(d,i) {return d;});	
	
// Underline via text-decoration.
// Note some inconsistency on Firefox, IE, etc. 
// Since underline in SVG has almost no variants, instead here the length of the underline is varied:  
svg.append("text")
    .attr("x",10).attr("y",115).text("Underline:")
  var uline = svg.selectAll("ulinetext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",115)
  	.attr("font-family", "Saira Extra Condensed")
  uline.append("tspan")
  	.attr("text-decoration","underline")
	  .text( function(d,i) {t=d+"\u2009".repeat(7); return t.substring(0,i);})
  uline.append("tspan")
    .attr("text-decoration","strike-through")
	  .text( function(d,i) {t=d+"\u2000".repeat(7); return t.substring(i,10) ;}); 

  // Widths via font-family (use a font with many widths):
  svg.append("text")
    .attr("x",10).attr("y",135).text("Width:")
  svg.selectAll("widthtext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
	  .attr("y",135)
	  .attr("font-family", function(d,i) {switch(i) {
										case 0: case 1: return "Saira Extra Condensed"; break;
										case 2: case 3: return "Saira Condensed"; break;
										case 4: case 5: return "Saira Semi Condensed"; break;
										default:  return "Saira"; }
										})
	  .text( function(d,i) {return d;});
	
// Tracking via letter-spacing:
// Note some inconsistency on Firefox, IE, etc.
svg.append("text")
    .attr("x",10).attr("y",155).text("Spacing:")
svg.selectAll("tracktext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",155)
  	.attr("letter-spacing", function(d,i) { return i*.05-.1 + "em";})
  	.attr("font-family", "Saira Condensed")
  	.text( function(d,i) {return d;})
	
// Baseline shift via dy
// Note provide a list for dy, each character is shifted by each successive dy value
svg.append("text")
    .attr("x",10).attr("y",175).text("Baseline:")
svg.selectAll("baseshifttext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",175)
  	.attr("dy", function(d,i) { return Math.sin(i)*3 +" "+ Math.sin(i+3)*3 + " " + Math.sin(i+6)*3+" ";})
  	.attr("font-family", "Saira")
  	.text( function(d,i) {return d;});
	
// Outline via stroke
svg.append("text")
    .attr("x",10).attr("y",195).text("Outline:")
svg.selectAll("outlinetext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",195)
  	.attr("fill","white")
  	.attr("stroke","black")
  	.attr("stroke-width",function(d,i) {return i*.15+.15;})
  	.attr("font-family", "Saira ExtraBold")
  	.text( function(d,i) {return d;});
	
// Combo, color + font
svg.append("text")
    .attr("x",10).attr("y",215).text("Font+Clr:")
svg.selectAll("combotext").data(data).enter().append("text") 
    .attr("x",function(d,i) {return i*40+100;})
  	.attr("y",215)
  	.attr("fill", function(d,i) {return clrs[i];})
  	.attr("font-family", function(d,i) {return fonts[i];})
  	.text( function(d,i) {return d;});
	
// Combo: fake dropshadow
svg.append("text")
    .attr("x",10).attr("y",235).text("Dropshadow")
var dropshadow = svg.selectAll("dropoffset").data(data).enter().append("g")
    .attr("transform", function (d,i) {return "translate(" + (i*40+100) + ",235)"; });
  // first draw the shadow text, slightly offset
  dropshadow.append("text") 
    .attr("dx",function(d,i) {return Math.sin(i)*1.6;})
  	.attr("dy",function(d,i) {return Math.cos(i)*1.6;})
    .attr("font-family", "Saira SemiBold")
  	.text( function(d) {return d;});
  // then draw the top text, in a different color
  dropshadow.append("text")
	  .attr("fill", function(d,i) {return clrs[i];})
	  .attr("font-family", "Saira ExtraBold")
	  .text( function(d,i) {return d;});
	
// Combo: Oblique + weight + baseline
svg.append("text")
    .attr("x",10).attr("y",255).text("Ob+Wt+Base")
obliquetext = svg.selectAll("obliquetext").data(data).enter().append("g") 
    .attr("transform", function (d,i) {return "translate(" + (i*40+100) + ",255)" +
                                            " skewX(" + (i*10-40) + ")"; });
  obliquetext.append("text")
  	.attr("dy", function(d,i) { return Math.sin(i)*3 +" "+ Math.sin(i+3)*3 + " " + Math.sin(i+6)*3+" ";})
  	.attr("font-family", "Saira")
  	.attr("font-weight",function(d,i) {return i*100+100;})
  	.text( function(d) {return d;});
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console