Pen Settings

HTML

CSS

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

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

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

Behavior

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.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <main>
<div class="box" aria-labelledby="box-title event-title">
	<div class="box-header-background"></div>
	<div class="box-header">
		<img src="https://placekitten.com/100/100" alt="" role="presentation" class="box-img" />
		<div class="box-title" id="box-title">Fluffy Meowington</div> <!-- if you make this name longer it should wrap -->
	</div>
	<div class="box-content">
		<div class="event-title">Event Title</div>
		<p class="event-text">A thing happened in Fluffy's life that is culturally or socially significant!</p>
		<ul class="list list-inline">
<!-- 			Since this area auto-updates based on other interactions, I'd want to think more about setting this as an aria-live region. They're typically irritating to me personally though, so I tend to avoid them. that's why I'd want to think about this some more before just doing it. -->
			<li class="list-item" id="js-interaction-congrats"><span class="count" id="js-count-congrats"></span> congrats</li>
			<li class="list-item" id="js-interaction-likes"><span class="count" id="js-count-likes"></span> like(s)</li>
		</ul>
		<div class="button-bar" role="group">
			<button class="button button-default" id="js-toggle-congrats" aria-pressed="false">Say Congrats!</button>
			<button class="button button-default" id="js-toggle-likes" aria-label="like this event" aria-pressed="false">
				<i class="fa fa-icon fa-thumbs-up fa-2x" aria-hidden="true"></i>
			</button>
		</div>
	</div>	
</div>
</main>
              
            
!

CSS

              
                $height-offset: 90px;
$base-font-size: 16px;
$box-width: 325px;
$background-color: transparent;
$black: #212121; //never use pure black
$gray-dark: #444444;
$interaction: blue;

*, *:after {
	box-sizing: border-box;
}

body {
	color: $gray-dark;
	font-family: 'Roboto', sans-serif;
	font-size: $base-font-size;
	line-height: 1.5;
}
main {
	@media screen and (min-width: 1200px){
	padding-left: 1em; //just to make this thing not hug the left wall
	}
}
.box {
	display: flex;
	flex-flow: row wrap;
	font-size: 16px;
	justify-content: center;
	max-width: 100%;
	min-width: $box-width;
	width: 100%;
	@media screen and (min-width: 500px) { //probably should be ems
		font-size: calc( 16px + 8 * ((100vw - 500px) / 1200));
		width: $box-width; //probably should be ems
		border: 1px solid rgba(0,0,0,0.1);
		border-radius: 4px;
	}
	@media screen and (min-width: 1200px) { //probably should be ems
		font-size: calc( 14px + 8 * ((100vw - 1200px) / 1500)); //look up the right way to do this
		
	}
	
	.box-header-background {
		background-image: url(https://placekitten.com/100/100);
		background-size: cover;
		clip-path: inset(0 0 0 0); //cleans up the fuzzy edges (but this doesn't have IE support)
		filter: blur(8px); 
		height: 152px;
		position: absolute; //ew ew ew ew 
		width: $box-width;
		z-index: -1;
	}
	.box-header {
		align-items: flex-end;
		display: flex;
		justify-content: space-between;
		width: 100%;

		.box-img {
			margin-left: 1em;
			transform: translateY(50px); 
			box-shadow: 1px 1px 1px rgba(0,0,0,0.5) //meh about this. Could take it or leave it.
		}
		.box-title { 
			color: white;
			filter: initial;
			flex: 1;
			font-size: 1.125em;
			font-weight: 400;
			letter-spacing: 1px;
			margin-top: $height-offset;
			padding: 0.75em 0.5em 0;
			text-align: right;
			text-shadow: 1px 1px 1px rgba(0,0,0,0.5);
		}
	}
	.box-content {
		background-color: $background-color;
		width: 100%;
		.event-title {
			font-size: 1.125em;
			font-weight: bold;
			margin-top: $height-offset/2;
			padding: 0.75em 0.75em 0;
		}
		.event-text {
			padding: 0.75em;
			margin: 0;
		}
	}
}

.list {
	display: flex;
	list-style: none;
	margin: 0;
	padding: 0;
	&.list-inline {
		padding: 0.75em;
		.list-item {
			font-size: 0.8em;
			&:first-of-type {
				&:after {
					content: ',';
					padding-right: 1px; //ugh hack
				}
			}
			&.has-interaction {
				color: $interaction;
			}
		}
	}
}

.button-bar {
	display: flex;
	margin-top: 1em;
	width: 100%;
	.button {
		background-color: lightgray;
		border-bottom-left-radius: 4px;		
		border-top-left-radius: 4px;
		border: 1px solid darkgray;
		font-family: 'Roboto', sans-serif;
		font-size: 0.9em;
		line-height: 1.5;
		padding: 0.75em;
		width: 75%;
		&:nth-of-type(2) {
			border-top-left-radius: 0;
			border-top-right-radius: 4px;
			border-bottom-left-radius: 0;
			border-bottom-right-radius: 4px;
			border-left: none;
			width: 25%; //this also doesn't really make me happy. 
		}
		&:hover {
			cursor: pointer;
		}
	}
}
.text-success {
	color: green;
}


//this widget has made me do most of the stuff I dislike in CSS. Everything feels like a hack. 
              
            
!

JS

              
                //let's try this w/o jQuery.tbh IRL this would be a contextual component in Ember and that would make it a lot easier. 

// declare all your variables first to be polite. 
var congratsCount, likesCount, congratsCountText, likesCountText, incrementCongratsCount, decrementCongratsCount, incrementLikesCount, decrementLikesCount, congratsInteraction, likesInteraction, congratsToggle, likesToggle;

//set the counts
congratsCount = 2;
likesCount = 3;

//"counts" text elements
congratsCountText = document.getElementById('js-count-congrats');
likesCountText = document.getElementById('js-count-likes');

//fill in the count data
congratsCountText.textContent = congratsCount;
likesCountText.textContent = likesCount;

//Increment/Decrement interactions
incrementCongratsCount = congratsCount + 1;
decrementCongratsCount = congratsCount - 1;
incrementLikesCount = likesCount + 1;
decrementLikesCount = likesCount -1;

//Interactions elements (we want the whole word, not just the count number)
congratsInteraction = document.getElementById('js-interaction-congrats')
likesInteraction = document.getElementById('js-interaction-likes');

//Toggle Buttons
congratsToggle = document.getElementById('js-toggle-congrats');
likesToggle = document.getElementById('js-toggle-likes');

//congrats toggle button
congratsToggle.addEventListener('click', function(){
	if (congratsInteraction.classList.contains('has-interaction')) {
			congratsCount--;  //decrement the count by one
			congratsCountText.textContent = congratsCount; //update the element with the new value
			congratsInteraction.classList.remove('has-interaction'); //remove the interaction indicator
		  congratsToggle.setAttribute('aria-pressed', 'false'); //update the aria-pressed property
			} else {
				congratsCount++; //increment the count by one
				congratsCountText.textContent = congratsCount; //update the element with the new value
				congratsInteraction.classList.add('has-interaction'); //add the interaction indicator
				congratsToggle.setAttribute('aria-pressed', 'true'); //update the aria-pressed property
			}
});

//likes toggle button
likesToggle.addEventListener('click', function() {
	if (likesInteraction.classList.contains('has-interaction')) {
		likesCount--; //decrement the count by one
		likesCountText.textContent = likesCount; //update the element with the new value
		likesInteraction.classList.remove('has-interaction'); //remove the interaction indicator
		likesToggle.setAttribute('aria-pressed', 'false'); //update the aria-pressed property
		likesToggle.classList.remove('text-success'); //remove visual indicator
	} else {
		likesCount++; //increment count by one
		likesCountText.textContent = likesCount; //update the element with the new value
		likesInteraction.classList.add('has-interaction'); //add the interaction indicator
		likesToggle.setAttribute('aria-pressed', 'true'); //update the aria-pressed property
		likesToggle.classList.add('text-success'); //give a visual indicator 
	}
});


// I suppose the "say congrats" toggle should not really be a toggle but rather send a message of congrats to Fluffy (in addition to the things it already does) but then what if you toggle the button again? Will the congrats message go away? Fluffy would be sad. this interaction doesn't feel "on purpose" enough, I need to think about this some more. 

// maybe the "say congrats" button could have a visual indicator that the user had left a congrats message (add a checkmark or something?)

//Also is this really how tedious plain JS is? It's so tedious. I want Ember back please. 
              
            
!
999px

Console