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.
<header class="app-header">
<h1 class="brand">
<a href="https://www.ediya.com/" target="_blank">
<span class="a11y-hidden">EDIYA COFFEE</span>
</a>
</h1>
<button type="button" class="button is-open">
<img src="navigation-button.gif" alt="메뉴 열기">
</button>
<nav hidden class="app-navigation">
<ul class="reset-list">
<li><a href="#">메뉴</a></li>
<li><a href="#">이디야멤버스</a></li>
<li><a href="#">이디야커피랩</a></li>
<li><a href="#">이디야컬쳐랩</a></li>
<li><a href="#">공지사항</a></li>
<li><a href="#">매장찾기</a></li>
</ul>
<button type="button" class="button is-close-menu" aria-label="메뉴 닫기">×</button>
</nav>
</header>
<main class="app-main">
<ul class="ediya-menu reset-list">
<li class="ediya-menu__item">
<a href="#">
<figure>
<img src="ICED-벚꽃라떼.png" alt width="323" height="323">
<figcaption>ICED 벚꽃라떼</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">ICED 벚꽃라떼<span lang="en">Cherry Blossom Latte</span></strong>
<p>은은한 벚꽃향과 라즈베리 화이트 초콜릿 토핑이 올라간 핑크빛 라떼</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(393kcal)</b></span>
<span>당류<b>(35g)</b></span>
<span>단백질<b>(7g)</b></span>
<span>포화지방<b>(18.6g)</b></span>
<span>나트륨<b>(149mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="HOT-벚꽃라떼.png" alt width="323" height="323">
<figcaption>HOT 벚꽃라떼</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">HOT 벚꽃라떼<span lang="en">Cherry Blossom Latte</span></strong>
<p>은은한 벚꽃향과 라즈베리 화이트 초콜릿 토핑이 올라간 핑크빛 라떼</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(430kcal)</b></span>
<span>당류<b>(38g)</b></span>
<span>단백질<b>(10g)</b></span>
<span>포화지방<b>(19.0g)</b></span>
<span>나트륨<b>(190mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="ICED-브라우니-쇼콜라.png" alt width="323" height="323">
<figcaption>ICED 브라우니 쇼콜라</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">ICED 브라우니 쇼콜라<span lang="en">Brownie Chocolate</span></strong>
<p>깊고 진한 초콜릿의 맛에 부드러운 휘핑크림과 브라우니를 함께 어울러져 고급스러운 디저트 같은 초콜릿 음료</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(503kcal)</b></span>
<span>당류<b>(42g)</b></span>
<span>단백질<b>(9g)</b></span>
<span>포화지방<b>(20.8g)</b></span>
<span>나트륨<b>(262mg)</b></span>
<span>카페인<b>(12mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="HOT-브라우니-쇼콜라.png" alt width="323" height="323">
<figcaption>HOT 브라우니 쇼콜라</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">HOT 브라우니 쇼콜라<span lang="en">Brownie Chocolate</span></strong>
<p>깊고 진한 초콜릿의 맛에 부드러운 휘핑크림과 브라우니를 함께 어울러져 고급스러운 디저트 같은 초콜릿 음료</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(503kcal)</b></span>
<span>당류<b>(42g)</b></span>
<span>단백질<b>(9g)</b></span>
<span>포화지방<b>(20.9g)</b></span>
<span>나트륨<b>(299mg)</b></span>
<span>카페인<b>(12mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="제주청귤-오리지널.png" alt width="323" height="323">
<figcaption>제주청귤 오리지널</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">제주청귤 오리지널<span lang="en">Jeju Green Tangerine Tea</span></strong>
<p>청정 제주지역에서 자라난 귀한 청귤의 풍부한 과육을 맛볼 수 있는 새콤달콤한 홈메이드 스타일 과일차</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(218kcal)</b></span>
<span>당류<b>(51g)</b></span>
<span>단백질<b>(0g)</b></span>
<span>포화지방<b>(0.1g)</b></span>
<span>나트륨<b>(4mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="제주청귤-블라썸.png" alt width="323" height="323">
<figcaption>제주청귤 블라썸</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">제주청귤 블라썸<span lang="en">Jeju Green Tangerine Blossom</span></strong>
<p>청귤의 새콤함이 복숭아, 포도 등의 다양한 과일향과 함께 어우러져 밸런스가 훌륭한 블렌딩티</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(202kcal)</b></span>
<span>당류<b>(46g)</b></span>
<span>단백질<b>(1g)</b></span>
<span>포화지방<b>(0.1g)</b></span>
<span>나트륨<b>(5mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="석류-오리지널.png" alt width="323" height="323">
<figcaption>석류 오리지널</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">석류 오리지널<span lang="en">Pomegranate Tea</span></strong>
<p>석류 특유의 산뜻한 향과 깔끔한 뒷맛이 느껴지며, 과육이 한알 한알 살아있는 붉은 빛의 매력적인 과일차</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(210kcal)</b></span>
<span>당류<b>(42g)</b></span>
<span>단백질<b>(0g)</b></span>
<span>포화지방<b>(0.1g)</b></span>
<span>나트륨<b>(5mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
<li class="ediya-menu__item">
<a href="#" target="_blank">
<figure>
<img src="석류-애플라임.png" alt width="323" height="323">
<figcaption>석류 애플라임</figcaption>
</figure>
</a>
<div hidden class="ediya-menu__item--detail">
<strong class="ediya-menu__item--name">석류 애플라임<span lang="en">Pomegranate Apple Lime</span></strong>
<p>산뜻한 석류에 다양한 과일과 꽃, 그리고 샴페인의 향이 더해져 보다 깊고 중후한 맛이 느껴지는 블렌딩티</p>
<div class="ediya-menu__item--multi-column is-2">
<p>
<span>칼로리<b>(220kcal)</b></span>
<span>당류<b>(42g)</b></span>
<span>단백질<b>(1g)</b></span>
<span>포화지방<b>(0.1g)</b></span>
<span>나트륨<b>(7mg)</b></span>
<span>카페인<b>(0mg)</b></span>
</p>
</div>
<button type="button" class="button is-close-panel" aria-label="아이템 소개 패널 닫기">×</button>
</div>
</li>
</ul>
</main>
::selection {
background: #233d84;
color: #ffffff;
}
body * {
-webkit-tap-highlight-color: rgba(255,255,200,0.3);
tap-highlight-color: rgba(255,255,200,0.3);
}
body {
margin: 0;
min-height: 100vh;
}
nav a {
color: inherit;
text-decoration: none;
}
a img {
vertical-align: middle;
}
/* --------------------------------------------
* 헤더 디자인 */
.app-header {
position: fixed;
z-index: 600;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
background: rgba(255,255,255,0.4);
margin-bottom: 30px;
border-bottom: 1px solid #e0e0e0;
}
/* 브랜드 디자인 */
.brand {
margin-top: 0;
margin-bottom: 0;
}
.brand a {
display: block;
width: 152px;
height: 15px;
padding: 26px;
background: url("ediya-logo.gif") no-repeat center;
background-size: 152px 15px;
}
/* 내비게이션 디자인 */
.app-navigation {
overflow: hidden;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding-top: 60px;
background: hsla(225, 57%, 10%, 0.9);
color: #fff;
transition: all 0.4s cubic-bezier(0.66,-0.01, 0.3, 0.99);
transform: translateX(105vw);
backdrop-filter: blur(2px);
}
.app-navigation.is-active {
transform: translateX(0);
}
.app-navigation li {
border-bottom: 1px solid hsla(225, 57%, 30%, 0.5);
}
.app-navigation a {
display: block;
padding: 1em;
transition: all 0.4s ease;
}
.app-navigation a:hover,
.app-navigation a:focus {
background: #2e437c;
}
/* 버튼 디자인 */
.app-header .button.is-open {
user-select: none;
padding: 20px;
background: #ffffff;
transition: all 0.3s ease;
}
.app-header .button.is-open:hover,
.app-header .button.is-open:focus {
background: #f5f5f5;
}
.app-navigation .button.is-close-menu {
position: absolute;
z-index: 10;
top: 10px;
right: 10px;
padding: 20px;
background: transparent;
color: #fff;
font-weight: 100;
font-size: 40px;
line-height: 0.5;
transition: all 0.4s ease;
}
.app-navigation .button.is-close-menu:hover {
transform: scale(1.2);
}
/* --------------------------------------------
* 메인 디자인 */
.app-main {
margin-top: 90px;
max-width: 960px;
margin-left: 20px;
margin-right: 20px;
box-sizing: border-box;
margin-bottom: 40px;
}
@media screen and (min-width: 960px) {
.app-main {
margin-left: auto;
margin-right: auto;
}
}
/* 메뉴 디자인 */
.ediya-menu {
display: flex;
justify-content: center;
align-items: center;
flex-flow: row wrap;
}
.ediya-menu__item {
position: relative;
flex: 1 1 40%;
margin: 10px 10px;
}
.ediya-menu__item a {
display: block;
background: #f5f5f5;
text-decoration: none;
color: #464646;
}
.ediya-menu__item figure {
margin: 0;
display: flex;
flex-direction: column;
text-align: center;
}
.ediya-menu__item img {
user-select: none;
max-width: 330px;
min-width: 240px;
width: 100%;
height: auto;
margin-left: auto;
margin-right: auto;
transform: scale(0.85);
transition: all 0.4s ease;
}
.ediya-menu__item a:hover img {
transform: scale(0.95);
}
.ediya-menu__item figcaption {
margin-top: -5px;
margin-bottom: 25px;
}
.ediya-menu__item--detail {
opacity: 0;
position: absolute;
z-index: 500;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 1px solid #e0e0e0;
padding: 30px 20px;
background: rgba(255,255,255,0.6);
transition: all 0.6s ease;
}
.ediya-menu__item--detail.is-active {
opacity: 1;
}
.ediya-menu__item--name {
display: block;
border-bottom: solid 2px #202023;
padding-bottom: 1em;
font-weight: 400;
font-size: 18px;
color: #202022;
}
.ediya-menu__item--name span {
display: block;
font-size: 14px;
color: #939394;
}
.ediya-menu__item--detail p {
line-height: 1.6;
font-size: 13px;
}
.ediya-menu__item--multi-column {
position: absolute;
left: 0;
right: 0;
bottom: 0;
column-gap: 20px;
column-fill: auto;
column-rule: 1px solid #aaa;
padding: 1em 1.5em;
background: #f8f8f8;
}
.ediya-menu__item--multi-column.is-2 {
column-count: 2;
}
.ediya-menu__item--multi-column p {
margin: 0;
}
.ediya-menu__item--multi-column span {
display: block;
}
.ediya-menu__item--detail .button.is-close-panel {
position: absolute;
top: 0;
right: 0;
padding: 9px 15px;
font-size: 24px;
background: transparent;
transition: all 0.3s ease;
}
.ediya-menu__item--detail .button.is-close-panel:hover {
background: #f3f3f3;
}
/* --------------------------------------------
* 공통 클래스 */
.reset-list {
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
list-style: none;
}
.button {
cursor: pointer;
border: none;
}
.a11y-hidden {
overflow: hidden;
position: absolute !important;
top: -9999em;
clip: rect(0, 0, 0, 0);
width: 1px;
height: 1px;
margin: -1px;
}
// -----------------------------------------------------------------------------------------
// 인터랙션 UI 디자인 - OffCanvas 메뉴 / Toggle 패널
// - DOM API, 변수, 함수, 조건문, 반복문, 연산자 등을 활용하는 총체적 예제.
//
// [1.1] EDIYA COFFEE 로고 오른쪽 옆에 위치한 토글 버튼(.button.is-open)을 누르면,
// 오프캔버스 메뉴(.app-navigation)을 화면에 표시한다.
// - hidden 속성 값 false 설정.
// - is-active 클래스 추가.
//
// [1.2] 오프캔버스 닫기 버튼(.button.is-close-menu)을 누르면,
// 오프캔버스 메뉴(.app-navigation)을 화면에서 감춘다.
// - hidden 속성 값 true 설정.
// - is-active 클래스 제거.
//
// [2.1] 이디야 메뉴 아이템(.ediya-menu__item)을 문서에서 모두 수집한 후,
// 메뉴 아이템 내부에서 a 요소를 찾아 클릭 이벤트를 연결한다.
// 이벤트에 연결된 함수(핸들러)는 음료 상세 설명 패널을 화면에 표시한다.
// - 상세 설명 패널(.ediya-menu__item--detail) hidden 속성 값 false 설정.
// - 상세 설명 패널에 is-active 클래스 추가.
//
// [2.2] 상세 설명 패널 내부에 위치한 패널 닫기 버튼(.button.is-close-panel)을 클릭하면,
// 패널을 닫는 이벤트 핸들러를 연결하여 패널을 닫도록 설정한다.
// - 상세 설명 패널(.ediya-menu__item--detail) hidden 속성 값 true 설정.
// - 상세 설명 패널에 is-active 클래스 제거.
//
//
// 예제 참고 URL: ediya.com/contents/drink.html
// ------------------------------------------------------------------------------------------
var app_header = null;
var menu_open_btn = null;
var app_navigation = null;
var menu_close_btn = null;
var app_main = null;
var ediya_menu = null;
var menu_items = null;
// 초기화
function init() {
// 문서 객체 접근 참조
accessingDOMElements();
// 오프캔버스 메뉴 접근성
a11yOffCanvasMenu(app_navigation);
// 이벤트 바인딩
bindEvents();
}
function accessingDOMElements() {
app_header = el('.app-header');
menu_open_btn = el('.button.is-open', app_header);
app_navigation = el('.app-navigation', app_header);
menu_close_btn = el('.button.is-close-menu', app_navigation);
app_main = el('.app-main');
ediya_menu = el('.ediya-menu');
menu_items = els('.ediya-menu__item', ediya_menu);
}
function bindEvents() {
for ( var i=0, l=menu_items.length; i<l; ++i ) {
var menu_item = menu_items[i];
var link = el('a', menu_item);
var close_panel_btn = el('.button.is-close-panel', menu_item);
link.addEventListener('click', openDetailPanel.bind(link, i));
close_panel_btn.addEventListener('click', closeDetailPanel);
}
menu_open_btn.addEventListener('click', openNavMenu);
menu_close_btn.addEventListener('click', closeNavMenu);
}
function openNavMenu() {
app_navigation.hidden = false;
window.setTimeout(function(){
app_navigation.classList.add('is-active');
}, 10);
}
function closeNavMenu() {
app_navigation.classList.remove('is-active');
window.setTimeout(function(){
app_navigation.hidden = true;
}, 600);
}
function openDetailPanel(index, e) {
e.preventDefault();
var detail = el('.ediya-menu__item--detail', menu_items[index]);
detail.hidden = false;
window.setTimeout(function(){
detail.classList.add('is-active');
}, 10);
}
function closeDetailPanel() {
var parent = this.parentNode;
parent.classList.remove('is-active');
window.setTimeout(function(){
parent.hidden = true;
}, 600);
}
init();
// -----------------------------------------------------------------
// 오프캔버스 메뉴 접근성
// -----------------------------------------------------------------
function a11yOffCanvasMenu(app_navigation) {
var nav_focusables = els('a, button', app_navigation);
var nav_focusable_first = nav_focusables[0];
var nav_focusable_last = nav_focusables[nav_focusables.length - 1];
window.addEventListener('keyup', escCloseMenu);
nav_focusable_first.addEventListener('keydown', navLastFocus);
nav_focusable_last.addEventListener('keydown', navFirstFocus);
function escCloseMenu(e){
if (e.keyCode === 27) { closeNavMenu(); }
}
function navFirstFocus(e) {
if (!e.shiftKey && e.keyCode === 9) {
window.setTimeout(function(){
nav_focusable_first.focus();
}, 10);
}
}
function navLastFocus(e) {
if (document.activeElement === e.target && e.shiftKey && e.keyCode === 9) {
nav_focusable_last.removeEventListener('keydown', navFirstFocus);
window.setTimeout(function(){
nav_focusable_last.focus();
nav_focusable_last.addEventListener('keydown', navFirstFocus);
}, 10);
}
}
}
Also see: Tab Triggers