cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmlicon-personicon-teamoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

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.

            
              

<div class="post right-align">

<p>"Now up comes Ted without any legs<br/>
And in their place there were two wooden pegs<br/>
She kissed him a dozen times or two<br/>
Saying “Holy moly could it be you?"</p>
  
</div>

<div class="post2">

<p>“Now was you drunk or was you blind<br/>
When you left your two fine legs behind?<br/>
Or was it out walking upon the sea<br/>
That tore your legs from the knees away?”</p>

</div>


<footer>
  <p>Based on the article and comments in: <br /><a href="https://webdesign.tutsplus.com/articles/getting-the-hang-of-hanging-punctuation--cms-19890">Getting the hang of hanging punctuation</a></p>
</footer>
            
          
!
            
              /**
 * hanging punctuation
 */

html
{
	font: 1.5em/1.5 Helvetica Neue, Georgia, serif;
	padding: 4em;
}

body
{
	border-left: 1px solid red;
	border-right: 1px solid red;
}

p
{
	position: relative;
	margin: 1.5em 0;
}

.hanging-start
{
	position: absolute;
	right: 100%;
}

.right-align {
  text-align:right;
}

.right-align .hanging-end { 
  position:absolute;
  left:100%;
}

.right-align .hanging-start { 
  position:static;
}

.justify p {
  text-align:justify;
  text-align-last: justify; 
}

footer
{
  text-align:center;
	font-size: 0.75em;
}
            
          
!
            
              /*
 * Hanging Punctuation
 * This function takes a DOM element,
 * searches each of its direct descendants,
 * and, if the element begins with hangable punctuation,
 * the appropriate HTML class is applied to the element.
 *
 * Then the parent DOM element get's a class to activate
 * the child classes we applied. 
 */
function hangPunctuation(container) {
 
    // Punctuation marks that qualify to be hung
    var marks = [
        '\u201c',     // “ - ldquo - left smart double quote
        '\u201d',     // ” - rdquo - right smart double quote
        '\u2018',      // ‘ - lsquo - left smart single quote
        '\u0022',     // " - ldquo - left dumb double quote
        '\u0027',      // ' - lsquo - left dumb single quote
        '\u00AB',      // « - laquo - left double angle quote
        '\u2039',     // ‹ - lsaquo - left single angle quote
        '\u201E',     // „ - bdquo - left smart double low quote
        '\u201A'    // ‚ - sbquo - left smart single low quote
    ];
         
    // Loop over all direct descendants of the container
    // If it's a blockquote, loop over its direct descendants
    for(i=0; i<container.children.length; i++) {
 
        var el = container.children[i];
 
        if (el.tagName === 'BLOCKQUOTE') {
            for (var k = 0; k < el.children.length; k++) {
                hangIfEligible(el.children[k]);
            };
        }
        else {
            hangIfEligible(el);
        }
    }
 
    // Check to see if the passed-in element 
    // begins or ends with one of the qualifying punctuation types
    // If it does, apply the appropriate class depending on the tag type
    function hangIfEligible(el) {
        var text = el.innerText || el.textContent;
        
        for(var i = 0; i < marks.length; i++) {
          
            // check if first char matches a hanging mark
            if ( text.indexOf(marks[i]) === 0 ) {
                el.innerHTML = '<span class="hanging-start">'+marks[i]+'</span>'+el.innerHTML.substr(1);
            }
          
            // check if last char matches a hanging mark
            if (text.substr(text.length-1).indexOf(marks[i]) === 0) {
                el.innerHTML = 
                  el.innerHTML.substr(0, el.innerHTML.length-1);
                el.innerHTML += '<span class="hanging-end">'+marks[i]+'</span>';
            }
        }
    }
}
 
window.onload = function() {
    var container = document.querySelector('.post')
    hangPunctuation( container );
    container = document.querySelector('.post2')
    hangPunctuation( container ); 
} 
            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console