From our sponsor: Chromatic - Visual testing for Storybook, Playwright & Cypress. Catch UI bugs before your users do.
Today we’d like to share a little template with you. This flexbox-based layout represents a weekly (5-day) surf report which shows some data of the day, like temperatures and information on waves. It is accompanied by an animating SVG graph that visualizes the wave data. When hovering over each day, a division of day periods becomes visible, each one showing relevant information depending on the time of the day. Additionally, when clicking on a live cam button, another content panel is slided into view. This panel shows an embedded Video with a live cam recording. We hope this little layout comes in handy for a column-based layout project or for your next animated SVG graph adventure.
Please note that this is highly experimental and lots of data is hard-coded. You could use it as a rough base to build your dynamic solution with it.
The structure
The initial HTML structure for our layout is the following:
<main class="theme-1">
<header class="codrops-header"><!-- ... --></header>
<!-- live cam panel -->
<div class="content content--cam">
<div data-type="youtube" data-video-id="lqmNApZXnGM"></div>
<button class="btn btn--close" aria-label="Close Live Cam">
<svg class="icon icon--cross">
<use xlink:href="#icon-cross"></use>
</svg>
</button>
</div>
<!-- graph panel -->
<div class="content content--graph">
<svg class="graph" viewBox="0 0 1440 800" preserveAspectRatio="none">
<defs>
<linearGradient id="gradient1">
<stop offset="0%" stop-color="#1231bb" />
<stop offset="100%" stop-color="#238DE0" />
</linearGradient>
<linearGradient id="gradient2" x1="0" x2="0" y1="0" y2=".7" xlink:href="#gradient1"/>
</defs>
</svg>
</div>
<!-- Button for toggling the live cam content -->
<button class="btn btn--cam btn--hidden">
<svg class="icon icon--cam icon--btn">
<use xlink:href="#icon-cam"></use>
</svg>
<span class="btn__text">Live Cam</span>
</button>
</main>
This includes the two panels for the live cam view and the graph view. We are going to dynamically build the resting HTML; a division for the day slices, and the graph path data. Furthermore, we’re using Plyr.js to embed a YouTube video in the cam panel.
The resulting HTML is the following:
<main class="theme-1">
<header class="codrops-header">
</header>
<div class="content content--cam">
<!-- ... -->
</div>
<div class="content content--graph">
<!-- all slices -->
<div class="slices">
<!-- single slice -->
<div class="slice slice--state-sunny">
<!-- weather states (show by toggling icons) -->
<div class="wstate-wrap">
<svg class="wstate wstate--sunny">
<use xlink:href="#state-sunny" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--cloudy">
<use xlink:href="#state-cloudy" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--partlycloudy">
<use xlink:href="#state-partlycloudy" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--rain">
<use xlink:href="#state-rain" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--thunders">
<use xlink:href="#state-thunders" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--clearnight">
<use xlink:href="#state-clearnight" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<svg class="wstate wstate--partlycloudynight">
<use xlink:href="#state-partlycloudynight" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
</div><!-- /wstate-wrap -->
<!-- weather data -->
<span class="slice__data slice__data--period slice__data--hidden">
<svg class="icon icon--clock"><use xlink:href="#icon-clock" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
<span class="slice__data slice__data--time"> </span>
</span>
<span class="slice__data slice__data--dateday">
<span class="slice__data slice__data--day">Today</span>
<span class="slice__data slice__data--date">11/21</span>
</span>
<span class="slice__data slice__data--air">
<svg class="icon icon--thermometer"><use xlink:href="#icon-thermometer" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
<span class="slice__data slice__data--temperature">28 °C</span>
</span>
<span class="slice__data slice__data--wind">
<svg class="icon icon--direction" style="transform: rotate(136.183deg);"><use xlink:href="#icon-direction" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
<span class="slice__data slice__data--wind-speed">3 km/h</span>
</span>
<span class="slice__data slice__data--swell">
<svg class="icon icon--wave"><use xlink:href="#icon-wave" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
<span class="slice__data slice__data--swell-height">2 m</span>
<span class="slice__data slice__data--swell-period">14 s</span>
</span>
<span class="slice__data slice__data--water">
<svg class="icon icon--thermometer"><use xlink:href="#icon-thermometer" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
<span class="slice__data slice__data--temperature">22 °C</span>
</span>
<!-- Hover overlay -->
<div class="slice__hover">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="slice slice--state-partlycloudy"><!-- ... --></div>
<!-- ... other slices -->
</div>
<svg class="graph" preserveaspectratio="none" viewbox="0 0 1440 800">
<defs>
<lineargradient id="gradient1">
<stop offset="0%" stop-color="#1231bb"></stop>
<stop offset="100%" stop-color="#238DE0"></stop>
</lineargradient>
<lineargradient id="gradient2" x1="0" x2="0" xlink:href="#gradient1" xmlns:xlink="http://www.w3.org/1999/xlink" y1="0" y2=".7"></lineargradient>
</defs>
<!-- animated SVG path -->
<path class="graph__path" d="..."></path>
</svg>
</div>
<!-- Button for toggling the live cam content -->
<button class="btn btn--cam">
<svg class="icon icon--cam icon--btn">
<use xlink:href="#icon-cam" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
<span class="btn__text">Live Cam</span>
</button>
</main>
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
Some interesting CSS
The interesting CSS is the part of the slices and slice data:
.slices {
position: absolute;
display: flex;
width: 100%;
height: 100vh;
}
.slice {
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
width: 20vw;
height: 100%;
padding: 5em 0 0 0;
pointer-events: none;
background: linear-gradient(200deg, #a0cfe4, #e8c37e);
}
/* The daytime periods show individual backgrounds */
/* we've grouped them, but you can differentiate it even more */
.slice--period-1,
.slice--period-6 {
background: linear-gradient(200deg, #6a8a98, #e8c37e);
}
.slice--period-2,
.slice--period-5 {
background: linear-gradient(200deg, #8db7ca, #e8c37e);
}
.slice--period-3,
.slice--period-4 {
background: linear-gradient(200deg, #a0cfe4, #e8c37e);
}
/* The slice data */
.slice__data {
font-size: 1.25vw;
line-height: 1.5;
position: relative;
z-index: 100;
display: flex;
padding: 1em;
}
.slice__data .slice__data {
display: inline-block;
padding: 0 0.5em 0 0;
vertical-align: middle;
white-space: nowrap;
}
.slice__data--hidden {
opacity: 0;
}
.slice__data--dateday {
color: #4682a5;
}
.slice__data--air,
.slice__data--wind,
.slice__data--water {
color: #4682a5;
}
.slice__data--period,
.slice__data--swell {
color: #fff;
}
.slice__data--swell {
font-size: 1.5vw;
margin-top: auto;
}
.slice__data--water {
margin-top: auto;
}
.slice__data .icon {
flex: none;
margin: 0 0.5em 0 0;
}
/* The weather icons */
/* Depending on the state, we switch the visibility of the respective icon */
.wstate-wrap {
font-size: 2em;
position: absolute;
z-index: 100;
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
}
.wstate {
position: absolute;
top: 0;
right: -40%;
width: 100%;
max-height: 100%;
opacity: 0;
}
.slice--state-sunny .wstate--sunny,
.slice--state-cloudy .wstate--cloudy,
.slice--state-partlycloudy .wstate--partlycloudy,
.slice--state-rain .wstate--rain,
.slice--state-thunders .wstate--thunders,
.slice--state-clearnight .wstate--clearnight,
.slice--state-partlycloudynight .wstate--partlycloudynight {
opacity: 1;
}
/* Hover areas */
.slice__hover {
position: absolute;
z-index: 1000;
top: 0;
left: 0;
display: flex;
width: 100%;
height: 100%;
pointer-events: auto;
}
.slice__hover div {
width: calc(100% / 6);
height: 100%;
}
.slice__hover div:hover {
background: rgba(0, 0, 0, 0.03);
}
All icons used in this template are included via SVG use
. The icons are added to a hidden SVG as symbols in the beginning of the HTML.
We hope this template is somehow useful to you!
Browser Support:- ChromeSupported
- FirefoxSupported
- Internet ExplorerSupported from version E
- SafariSupported
- OperaSupported
References and Credits
- Material icons by Google
- Weather icons by Pixel Buddha
- Other icons made by Freepik from www.flaticon.com
- Anime.js by Julian Garnier
- Plyr.js by Sam Potts
- Catmull-Rom Spline to Bezier Spline Converter by Nate Vack
- select-css by Filament Group
Hi, good job as always!
I found a bug on the location selector: http://i.imgur.com/Pjs4F3L.png
Thanks Tiago! Fixed 🙂 Cheers, ML
Like the cam. Wicked left hander!
> Anime.js by Julian Garnier
bad link
Fixed. Thanks!
I feel like the Live Cam button could be much more prominent, didn’t even realise it was there until I read through the article and went searching. Otherwise, quite cool!
Any idea where we can find the swell data? Was hoping for a free API 🙂
There is a site called magicseaweed which provides an API with a fair use policy of 1M request per month.
Good one! Thank you for sharing.
Interesting!
Pls leave arrifana out of this, its crowded af as it is right now.
You did an impressive template, Mary Lou.
Thanks!
Wonderful template! Thank you for sharing.
Anyone know where to plugin an API from a API source like Magicseaweed or NOAA on this given code?
Hey- for some reason the waves do not show up anymore- is there an issue?
Thanks for letting us know! It was an HTTPS problem because of our recent switch. We’ve fixed it now 🙂 (you might need to do a hard reload).
So cool!!but why it can’t run normally on chrome?
How can I load data from another place to use it?
It’s great!!!
But as rocky_nupt mentioned above, waves do not show up on Chrome.(I can see it on IE)
On the other hand, Icons such as thermometor and wind-arrow do not show up in IE, but I can see it on Chrome.
Is there anyone who can let me get advised how to fix it?