HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body> tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html> tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body> tags in a basic HTML5 template. If you need things in the <head> of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit- or -moz-.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
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.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<h1>Carousel Experiment (Button Tags)</h1>
<p><label>Field before: <input type="text" name="before" id="before"></label></p>
<div id="carousel" aria-labelledby="cLabel" role="region">
<h2 class="sr" aria-hidden="true" id="cLabel">News Items</h2>
<ul>
<li>
<div class="img">
<img src="http://www.test.assist.vt.edu/sandbox/assets/img/carousel/VT112188_2015181601.JPG"
alt="Researcher in lab">
</div>
<div class="blurb">
<h3>
<a href="story1.html">Researchers closer to understanding how certain cancers
resist treatment</a>
</h3>
<p>And here is some blurb text.</p>
</div>
</li>
<li>
<div class="img">
<img
src="http://www.test.assist.vt.edu/sandbox/assets/img/carousel/VT109124_20150619023.JPG"
alt="Exercisers in spinning class look forward with determination">
</div>
<div class="blurb">
<h3>
<a href="story2.html">How did Virginia Tech become the fittest campus in America?</a>
</h3>
<p>And here is some blurb text.</p>
</div>
</li>
<li>
<div class="img">
<img
src="http://www.test.assist.vt.edu/sandbox/assets/img/carousel/1459353411656.jpg"
alt="Smiling student against backdrop of campus building">
</div>
<div class="blurb">
<h3>
<a href="story3.html">Nneoma Nwankwo named Virginia Tech's Undergraduate Student of the Year</a>
</h3>
<p>And here is some blurb text.</p>
</div>
</li>
</ul>
</div>
<p><label>Field after: <input type="text" name="after" id="after"></label></p>
<hr/>
<h2>Comments</h2>
<p>Inspired by <a href="https://www.w3.org/WAI/tutorials/carousels/">WAI example</a>, but modified.</p>
<p>This implementation of the carousel pattern uses button tags for the individual slide navigation controls. The disadvantage of this is that its is not really semantically correct, in that this is really a group of buttons, only one of which can be selected, like a radio button group. For implementation of the radio group pattern, see other pen.</p>
<p>Tested with JAWS 16/ IE 11, NVDA 2015.4/ Firefox 45.0.2, VoiceOver/Safari on OS X El Capitan (10.11.3)</p>
<h3>Problems:</h3>
<p>While the slideshow pauses if focus is on a focusable element in the carousel, such as the slide navigation controls, if one is using the virtual cursor to navigate through the page the content where the cursor is can change.</p>
<p>Hiding part of the button label may make it slightly harder for speech recognition users to activate controls.</p>
<h4>OS X/VoiceOver/Safari:</h4>
<ul><li>Occasionally, in response to a button press, the navigation keys stop working as expected, and, instead, move the visible cursor about the page</li></ul>
<h4>iOS/VoiceOver/Safari:</h4>
<ul>
<li>The first time you activate a liveControl, focus is shifted to the start of the page. I've noticed this before on some other widgets. Is this an iOS bug? If so, how do I fix?</li>
<li>The blurb text in the live region is not voiced, just the image and heading. Why?</li>
<li>When focus moves past carousel, it doesn't resume playing, though it does if I move before it.</li>
<li>Occasionally, it just freaks out (to be technical).</li>
</ul>
<h4>JAWS 16/IE</h4>
<ul>
<li>When the live region changes, only the heading text (and not the image alt text) is voiced and that is voiced twice.</li>
</ul>
<h4>NVDA/Firefox</h4>
<ul>
<li>When you return to the Play/Pause button from a liveControl, it is voiced as being "SVG Play Icon (suspended)", even though shifting focus to it has caused it to change back to "SVG Pause Icon"</li>
</ul>
.sr {
position: absolute;
clip: rect(1px 1px 1px 1px); /* for Internet Explorer */
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
}
#carousel {
position: relative;
max-height: 31.25rem;
overflow: hidden;
width:100%;
}
#playContainer {
position: absolute;
z-index: 1000;
padding: .5rem;
}
.img {
position: relative;
}
.img img {
width:100%;
}
.blurb {
position: absolute;
bottom: 0;
width: 100%;
padding: .5rem;
padding-bottom: 2rem;
linear-gradient(transparent, black);
background-image: linear-gradient(transparent, black);
color: white;
font-family: 'Lato', sans-serif;
}
.blurb h3 {
font-size: 2em;
text-shadow: 2px 2px 0px #000;
margin-bottom: 0;
}
.blurb a {
color: #fff;
text-decoration: none;
}
.blurb a:hover, .blurb a:focus {
text-decoration: underline;
}
#ctrls {
position: absolute;
bottom: 0;
z-index: 1001;
padding: .5rem;
}
#bullets, #prevNext {
display: inline;
padding: 0;
}
#bullets li, #prevNext li {
display: inline;
}
#bullets button, #prevNext button {
margin-right: .4em;
}
.activeBullet button {
background-color: yellow;
}
/* Progressive enhancement: Hides carousel until ready */
.js #carousel {
display:none;
}
$(document).ready(function(){
makeCarousel();
function makeCarousel() {
var carousel = $('#carousel'); //Container for the slides and playback controls
var numSlides = $('#carousel ul li').length; //The number of slides in the list
var currentSlide = 0; //The index of the li in the ul for the slide currently displayed
var playing = false; //Whether slideshow is currently playing
var intervalID; //Reference to timer, so it can be removed to stop slideshow
var fromCarousel = false; //Whether focus had been on something in the carousel (except playPause)
var slideList = $('#carousel ul').detach(); //Remove list from page, to pull slides from later
//CREATE LIVE REGION AND CONTROLS AND ADD THEM TO PAGE
//Create live region where slides will be displayed (aria-live state indicates whether to voice changes)
var slideDisplay = $.parseHTML(
'<div id="slideDisplay" ' +
'role="region" ' +
'aria-label="Currently Displayed Slide" ' +
'aria-live="off" ' +
'aria-relevant="additions" ' +
'aria-atomic="false">' +
'</div>');
//Create container for the controls that let you move between slides
var ctrls = $.parseHTML('<nav id="ctrls" aria-label="Slide Navigation"></nav>');
//Create list of bullet buttons for moving to particular slides
var bullets = $.parseHTML('<ul id="bullets" aria-label="Individual Navigation"></ul>');
for (var i = 1; i <= numSlides; i++) {
$(bullets).append('' +
'<li>' +
'<button ' +
'class="liveControl" ' +
'aria-controls="slideDisplay">' +
'<span class="sr">Slide </span>'+i+
'</button>' +
'</li>');
}
//Create list containing previous and next buttons
var prevNext =
'<ul id="prevNext" aria-label="Sequential Navigation">'+
'<li>' +
'<button ' +
'id="prev" ' +
'class="liveControl" ' +
'aria-label="Previous Slide" ' +
'aria-controls="slideDisplay">' +
'SVG Previous Icon' +
'</button>' +
'</li>' +
'<li>' +
'<button ' +
'id="next" ' +
'class="liveControl" ' +
'aria-label="Next Slide" ' +
'aria-controls="slideDisplay">' +
'SVG Next Icon' +
'</button>' +
'</li>' +
'</ul>';
//Create play/pause toggle button
var playContainer =
'<div id="playContainer">' +
'<button ' +
'id="playPause" ' +
'aria-label="Play" ' +
'aria-describedby="ctrlDesc" ' +
'aria-controls="slideDisplay">' +
'SVG Play Icon' +
'</button>' +
'<br /> '+
'<span ' +
'class="sr" ' +
'aria-hidden="true" ' +
'id="ctrlDesc">' +
'Plays/pauses slideshow. Slide display follows.' +
'</span>' +
'</div>';
//Add controls to carousel
carousel.append(slideDisplay);
$(ctrls).append(prevNext).append(bullets);
carousel.append(ctrls);
carousel.prepend(playContainer);
//When user clicks on bullet button, show that slide and style the current button
$("#bullets").find('button').click(function() {
var item = $(this).closest('li');
currentSlide = $(item).index();
activate(currentSlide);
event.stopPropagation();
});
//When user clicks previous button go to the previous slide
$("#prev").click(function(event) {
prevSlide();
event.stopPropagation();
});
//When user clicks next button go to the next slide
$("#next").click(function(event) {
nextSlide();
event.stopPropagation();
});
//When user clicks the play/pause toggle button, start or pause the slideshow
$("#playPause").click(function(event) {
togglePlay();
event.stopPropagation();
});
/*
If focus is on something that can cause a slide change, we want SR to voice changes to the slide display,
but we don't want the slideshow to be automatically progressing, so we pause the slideshow
*/
carousel.on('focusin', function(event) {
//The exception is that, if focus is on playPause button, we don't want to suspend carousel,
// because it might confuse the user to click on play and have it not do anything
if ($(document.activeElement).attr('id')==='playPause') {
if (fromCarousel) {
voiceChanges(false);
resume();
}
fromCarousel = false;
} else {
fromCarousel = true;
suspend();
voiceChanges(true);
event.stopPropagation();
}
});
/*
If focus had been in the carousel, but then leaves it, either by tabbing out of it, or clicking elsewhere,
then resume the slideshow and turn off live updates
* */
$(document).on('focusin', function(event) {
if (fromCarousel) {
voiceChanges(false);
resume();
}
fromCarousel = false;
}).on('click', function(event) {
if (fromCarousel && !$(event.target).hasClass('liveControl')) {
voiceChanges(false);
resume();
}
fromCarousel = false;
})
//Activate the first slide
activate(currentSlide);
//Avoids flash of unstyled content
$("html").removeClass("js");
//Show slide and highlight related bullet button
function activate(i) {
showSlide(currentSlide);
setActive(currentSlide);
}
//Take the contents of the selected list item and put in the slide display region
function showSlide(i) {
$(slideDisplay).html($(slideList).find('li:nth-child('+(i+1)+')').html());
}
//Show which slide is being displayed by highlighting related bullet button
function setActive(i) {
$('li.activeBullet').removeClass('activeBullet');
currentItem = $('ul#bullets li:nth-child('+(i+1)+')');
currentItem.addClass('activeBullet');
$('span.activeIndicator').remove();
currentItem.append('<span class="sr activeIndicator"> (Current Slide)</span>');
}
//Start or pause slideshow depending on whether it is playing currently
function togglePlay() {
if (playing) {
$('#playPause').html('SVG Play Icon').attr('aria-label', 'play');
pause();
playing = false;
} else {
$('#playPause').html('SVG Pause Icon').attr('aria-label', 'pause');
play();
playing = true;
}
}
//Start slideshow
function play() {
intervalID = setInterval(nextSlide, 5000);
}
//Pause slideshow
function pause() {
clearInterval(intervalID);
}
//Show previous slide
function prevSlide() {
currentSlide = (currentSlide === 0) ? numSlides-1 : currentSlide - 1;
activate(currentSlide);
}
//Show next slide
function nextSlide() {
currentSlide = (currentSlide === numSlides-1) ? 0 : currentSlide + 1;
activate(currentSlide);
}
//Make the ARIA live region politely announce changes
function voiceChanges(toggle) {
$(slideDisplay).attr('aria-live', toggle ? 'polite' : 'off');
}
//If slideshow is playing, put it in a suspended state, so it can resume playing when no longer on liveControl
function suspend() {
if (playing) {
$('#playPause').html('SVG Play Icon (suspended)')
.attr('aria-label', 'Play (suspended)')
.addClass('suspended');
pause();
}
}
//If slideshow was playing when suspended, start it back up
function resume() {
if (playing) {
$('#playPause').html('SVG Pause Icon').attr('aria-label', 'Pause').removeClass('suspended');
play();
}
}
}
});
Also see: Tab Triggers