Many graphic effects that were previously only possible using a graphics editor are now feasible thanks to a combination of simple CSS rules. This trend is often referred to as “CSS Art”, a term that indicates the use of CSS for the creation of graphic experiments where the CSS bosses the show — whether it be images or real animations.
A few beautiful examples of CSS art that you may have seen include Homer Simpson and Darth Vader, both created with pure CSS.
In this article, I’ll show you how to draw a small vintage television created using HTML5 and CSS3 with the addition of few lines of JavaScript to simulate the possibility to show different channels (actually videos taken from YouTube).
It should be noted that although a user may be attracted by these effects, probably in some cases they are taken to extremes. We would always want to ensure that any technique we use isn’t affecting the performance or maintainability of our code.
Here’s a CodePen demo showing what we’ll be creating:
See the Pen CSS3 and JavaScript Vintage TV by SitePoint (@SitePoint) on CodePen.
A Brief BEM Intro
For this project we’ll use the BEM methodology for naming our CSS classes.
Explaining BEM in great detail is outside the scope of this article, but here I’ll cover it briefly.
The acronym BEM stands for Block Element Modifier. This methodology suggests a structured way of naming classes, based on the properties and role of the element in question. To adhere to the BEM methodology, we have to stick with a naming convention that follows this pattern:
block
represents the higher level of an abstraction or component.block__element
represents a descendent of block that helps formblock
as a whole.block–modifier
represents a different state or version ofblock
.
BEM lets us to be more descriptive and explicit since we are able to understand relations with other elements of our code through naming. By reading the HTML code with the classes assigned, you can see how the chunks (blocks, elements, variation or modifier of those elements) are related and how they work.
Let’s see how BEM works; then, we’ll see it applied to our television.
For a quick example, think about how the following elements are related and how they are named:
<article class="book">
<img src="/path/to/image.jpg" class="book__cover book__cover--large" />
<h1 class="book__title">The little prince</h1>
</article>
That should give you a good intro to what BEM is. For a deeper discussion, check out Harry Roberts’ article. Now let’s move on to the code for our television.
The HTML for the Television
The markup underpinning the television is, as is the case with much CSS art, fairly deep, but not too difficult to grasp when looking at the BEM-based class names:
<div class="television">
<div class="television__top">
<div class="television__antenna television__antenna--left"></div>
<div class="television__antenna television__antenna--right"></div>
<div class="television__antenna__base"></div>
</div><!-- television__top -->
<div class="television__center">
<div class="television__screen">
<iframe src="" frameborder="0" allowfullscreen></iframe>
</div><!-- television__screen -->
<div class="television__channels-wrapper">
<ul class="television__channels">
<li class="television__channel"><a href="http://www.youtube.com/embed/SRu6YRr1KtM" title="Channel 1"></a></li>
<li class="television__channel"><a href="http://www.youtube.com/embed/oRdxUFDoQe0" title="Channel 2"></a></li>
<li class="television__channel"><a href="http://www.youtube.com/embed/EGikhmjTSZI" title="Channel 3"></a></li>
<li class="television__channel"><a href="http://www.youtube.com/embed/06qJVpUSKZY" title="Channel 4"></a></li>
<li class="television__channel"><a href="http://www.youtube.com/embed/v_09wFxoaeQ" title="Channel 5"></a></li>
<li class="television__channel"><a href="http://www.youtube.com/embed/Tj75Arhq5ho" title="Channel 6"></a></li>
</ul>
</div><!-- television__channels-wrapper -->
</div><!-- television__center -->
<div class="television__base">
<div class="television__foot television__foot--left"></div>
<div class="television__foot television__foot--right"></div>
</div><!-- television__base -->
</div><!-- television -->
Here’s a quick breakdown of what we’ve done here in the HTML:
- There are three main sections inside the .television container: top, center, and base.
- The top section is what holds the antenna parts
- The center holds the screen and the channels
- The base holds the feet of the TV
Notice that these three main sections, as well as the inner elements are named using a double underscore, which, in BEM, represents an element of the higher level block.
Next to some of these classes, (for example, when constructing the antenna) we have names like television__antenna--left
and television__antenna--right
. The reason for such names is that while the element is an antenna, we have to modify the element to act as the left or the right antenna respectively. So, the final part of the name suggests that all the rules we’ll apply to that particular class will define its style. In this case, they’ll define the style of the left or the right antenna of our vintage television.
The question is not so hard to understand and this example should reinforce the concepts explained while discussing BEM. There is a block which can contain one or more elements and these descendent elements can have one or more specific characteristics, intended as modifiers. The remainder of the HTML follows a similar BEM pattern.
The television__screen
element has is its only child, the iframe
, that we’ll use to display the videos loaded from YouTube. The television__channels--wrapper
contains an unordered list (<ul>
), which will hold the videos we want to be played when one of the six channel buttons is clicked. The href
attribute will be used to modify the load the intended video, which we’ll get to later.
Note also that in this project we’ve used <div>
s because we don’t need tags with any kind of semantic meaning.
Now it’s time to have move on to our CSS.
The CSS for our Television
In this section, we’ll only consider the relevant portions of the CSS, so some generic rules have been left out of the code here. Let’s take a look:
iframe {
box-sizing: border-box;
width: 100%;
height: 100%;
overflow: hidden;
border: 10px solid;
border-radius: 32px;
}
.television {
width: 450px;
margin: 0 auto;
}
.television__top {
width: 40%;
margin: auto;
position: relative;
}
.television__antenna {
width: 5px;
height: 100px;
background-color: #3b3733;
margin-bottom: -10px;
}
.television__antenna--left {
transform: rotate(-30deg);
float: left;
}
.television__antenna--right {
transform: rotate(30deg);
float: right;
}
.television__antenna__base {
height: 20px;
background-color: #3b3733;
border-top-left-radius: 48px;
border-top-right-radius: 48px;
margin-bottom: 10px;
clear: both;
position: relative;
z-index: 2;
}
Here’s a point by point summary of the important aspects of the CSS:
- We’ve used the
transform
property to position the antenna parts, one rotated clockwise, the other counter-clockwise. - A negative margin and the
float
property help us establish the position of the antenna parts in relation to the TV, and to each other. - We further use
clear
andz-index
to ensure the float doesn’t cause problems to the layout of subsequent elements and the antenna elements are stacked correctly. - To ensure the iframe looks ‘rounded’ in all browsers, we use a border trick.
Let’s now look at the code for the center part of the television:
.television__center {
position: relative;
z-index: 2;
width: 350px;
height: 200px;
background-color: #7a4e27;
border: solid 3px #eef4c4;
box-shadow: -10px -10px #d64832;
border-radius: 48px;
margin: 0 auto;
padding: 10px 15px;
}
.television__screen {
width: 270px;
height: 190px;
background-color: #eed5b6;
border-radius: 48px;
float: left;
}
.television__channels-wrapper {
width: 70px;
height: 190px;
background-color: #efd6b7;
border-radius: 48px;
float: right;
}
.television__channels {
padding: 0;
}
.television__channel {
list-style-type: none;
background-color: #7f4b23;
width: 25px;
height: 25px;
border-radius: 50%;
margin: 5px;
float: left;
position: relative;
}
.television__channel a {
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #e6a146;
width: 12px;
height: 12px;
border-radius: 50%;
}
.television__channel a:active {
box-shadow: inset rgba(255,255,255,0.6) 0 2px 2px,
inset rgba(0,0,0,0.15) 0 -2px 5px, /* inner shadow */
rgba(100,100,100,0.6) 0 2px 1px,
rgba(100,100,100,0.6) 0 2px 1px; /* color border */
}
Here are the main points from the code above:
z-index
is used to correctly stack the TV over the feet- The “vintage” effect for our television is created by a combination of shadows, borders, colors and padding.
- The channel buttons are created with a 50%
border-radius
, which creates a circle at any element size. - The channel buttons are individually centered vertically and horizontally and vertically using
transform: translate(-50%, -50%)
. - We use the
:active
pseudo-class to style the ‘clicked’ state of the channels, using shadows and borders to create the effect.
Finally, let’s look at the last section of our CSS, shown below.
.television__base {
width: 60%;
margin: auto;
}
.television__base:after {
clear: both;
content: "";
display: table;
}
.television__foot {
width: 20px;
height: 70px;
margin-top: -20px;
background-color: #7d4d25;
border: solid 3px #eed5b6;
border-radius: 48px;
}
.television__foot--left {
transform: rotate(30deg);
float: left;
}
.television__foot--right {
transform: rotate(-30deg);
float: right;
}
And here’s a description of the key parts of the above code:
- We use a clearfix method to fix a float/clearing issue.
- We’ve applied the same rotation of 30 degrees of the antennas also to the feet of the television, along with
float: left
andfloat: right
to bring them closer.
The JavaScript to Make the Channels Work
The last section of this article focuses on the small JavaScript code that enables the demo to show some videos when the channel button are pressed. With the iframe
element in place in our markup, loading videos from YouTube is very easy. Our goal is to attach a handler to be executed when a click is performed on a button of the panel.
Here is the code:
var buttons = document.querySelectorAll('.television__channel a');
for(var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
document.querySelector('.television__screen iframe').src = this.href;
event.preventDefault();
});
}
Here we use querySelectorAll
select the buttons, that is the a
elements inside the list items having a class of .television__channel
, which in a variable called buttons
. Then we iterate over each element retrieved to attach a handler using the addEventListener()
method to run when the click
event is triggered on it.
Inside the click handler we have to perform only two actions. The first is to set that very URL as the src
of the iframe
element. The second one is to prevent the default action, that in this case is to load the page specified by the URL of the href
attribute. With these lines in place, the browser will load the video from YouTube ready to be played. Cool, isn’t it?
Demo and Conclusion
Once again, here is the demo display our working TV:
See the Pen CSS3 and JavaScript Vintage TV by SitePoint (@SitePoint) on CodePen.
As mentioned in the introduction, these types of CSS experiments aren’t always the most practical way to create graphics. This is more a way to see what’s possible with CSS, and maybe help you learn some techniques along the way.
And although we could have used pseudo-elements to produce many of the elements, it might in fact be easier to do it all in the HTML, so it’s clear where our different elements are placed.
Frequently Asked Questions about Creating a Vintage Television using BEM, CSS3, and JavaScript
How can I create a vintage television using BEM, CSS3, and JavaScript?
Creating a vintage television using BEM, CSS3, and JavaScript involves a series of steps. First, you need to understand the basics of BEM, CSS3, and JavaScript. BEM (Block, Element, Modifier) is a methodology that helps you to create reusable components and code sharing in front-end development. CSS3 is the latest evolution of the Cascading Style Sheets language and aims at extending CSS2.1. It brings a lot of long-awaited novelties, like rounded corners, shadows, gradients, transitions or animations, as well as new layouts like multi-columns, flexible box or grid layouts. JavaScript is a programming language that allows you to implement complex features on web pages. Once you have a good understanding of these, you can start creating your vintage television. The process involves creating the television frame, the screen, the dials, and the buttons. You can then use JavaScript to add functionality to the dials and buttons.
What are the key differences between creating a vintage television and a modern one?
The key differences between creating a vintage television and a modern one lie in the design and functionality. Vintage televisions have a distinct design characterized by a boxy frame, a curved screen, and large dials and buttons. Modern televisions, on the other hand, have a sleek design with a flat screen and minimal buttons. In terms of functionality, vintage televisions have basic features like changing channels and adjusting volume. Modern televisions have advanced features like internet connectivity, streaming services, and voice control. When creating a vintage television using BEM, CSS3, and JavaScript, you need to replicate the vintage design and functionality.
Can I use other programming languages to create a vintage television?
Yes, you can use other programming languages to create a vintage television. However, BEM, CSS3, and JavaScript are particularly suited for this task because they allow you to create interactive and visually appealing web elements. BEM helps you to create reusable components, CSS3 allows you to style these components, and JavaScript enables you to add functionality to the components. If you prefer to use other languages, you need to ensure that they can provide similar capabilities.
How can I add functionality to the dials and buttons of the vintage television?
You can add functionality to the dials and buttons of the vintage television using JavaScript. JavaScript is a programming language that allows you to implement complex features on web pages. You can use it to make the dials and buttons interactive. For example, you can use JavaScript to change the channel when the dial is turned or adjust the volume when the button is pressed. You need to write a JavaScript function for each action and attach it to the corresponding dial or button.
Can I customize the design of the vintage television?
Yes, you can customize the design of the vintage television. The design is defined by the CSS3 styles, which you can modify to suit your preferences. You can change the color, size, shape, and other attributes of the television frame, screen, dials, and buttons. However, you need to maintain the vintage look and feel of the television. You can also add additional elements like antennas and legs to enhance the vintage design.
How can I make the vintage television responsive?
You can make the vintage television responsive by using CSS3 media queries. Media queries allow you to apply different styles for different devices based on their screen size, resolution, and other characteristics. You can use them to adjust the size and layout of the television so that it looks good on all devices. You can also use JavaScript to adjust the functionality of the dials and buttons based on the device.
Can I use the vintage television in a real project?
Yes, you can use the vintage television in a real project. However, you need to ensure that it fits the project requirements and target audience. The vintage television can be a great addition to a retro-themed website or a digital art project. You can also use it as a learning tool to practice your BEM, CSS3, and JavaScript skills.
How can I optimize the performance of the vintage television?
You can optimize the performance of the vintage television by following best practices in BEM, CSS3, and JavaScript. In BEM, you should use reusable components to reduce code duplication. In CSS3, you should use efficient selectors and properties to reduce rendering time. In JavaScript, you should use efficient algorithms and data structures to reduce execution time. You should also minify and compress your code to reduce its size and load time.
Can I animate the vintage television?
Yes, you can animate the vintage television using CSS3 animations and transitions. CSS3 animations allow you to change from one CSS style to another. You can use them to animate the screen, dials, and buttons. For example, you can animate the screen to simulate the flickering effect of a real vintage television. CSS3 transitions allow you to smoothly change from one CSS style to another over a certain time period. You can use them to create a smooth interaction when the dials are turned or the buttons are pressed.
Can I add sound to the vintage television?
Yes, you can add sound to the vintage television using JavaScript and HTML5 audio. JavaScript allows you to control the audio playback, while HTML5 audio allows you to embed audio files in your web page. You can add sound effects for the channel changing and volume adjusting actions. You can also add background noise to simulate the static sound of a real vintage television. However, you need to ensure that the sound enhances the user experience and does not annoy the users.
I have a Bachelor's degree in European languages, cultures, and literature from the University of Naples. I'm passionate about graphics and web design, and for several years I've been working on projects and designs for many companies. I'm a writer for the Audero User Group; my specialties are HTML, CSS, Web Design, and Adobe Photoshop.