It's less than a week to Christmas, and I'd like to welcome you to the traditional Christmas-themed web tutorial!
This year, just as we did back in 2017, we will be working with LESS. Nothing fancy, just that we will have multiple themes for the stylesheets and something like LESS makes sense. What we are attempting to create is a randomly generated online Christmas card with a random theme and a random message. This will be accomplished using PHP. With that in mind, let's proceed!
First, we have two folders -
img and
css.
index.php will be in the main folder.
styles.less will be in the
css folder, with the LESS JavaScript file in the
js folder. Three images will be in the
img folder.
|
img/snow.jpg |
|
img/food.jpg |
|
img/nativity.jpg |
We have some HTML here, with a reference to the LESS file and the JavaScript file for LESS.
index.php<!DOCTYPE html>
<html>
<head>
<title>Xmas 2023</title>
<link rel="stylesheet/less" type="text/css" href="css/styles.less" />
<script src="js/less.min.js"></script>
</head>
<body>
</body>
</html>
We will insert a placeholder for the body tag's class.
index.php<body class="theme_">
</body>
Within, we will have a div styled using
card.
index.php<body class="theme_">
<div class="card">
</div>
</body>
And inside that, we have three more divs, one styled using
image and the other styled using
greeting. The last one is just to offset whatever the
float properties for
image and
greeting eventually become.
index.php<body class="theme_">
<div class="card">
<div class="image">
</div>
<div class="greeting">
</div>
<div style="clear: both"></div>
</div>
</body>
And we'll have a header and paragraph tag inside the div styled by
greeting.
index.php<body class="theme_">
<div class="card">
<div class="image">
</div>
<div class="greeting">
<h1></h1>
<p></p>
</div>
<div style="clear: both"></div>
</div>
</body>
The LESS file starts with some styling for the html and body tags. This basically just defines font size and resets margins and padding. We also define centered so that we can use this as a mixin for other classes later.
css/styles.lesshtml, body
{
height: 100%;
padding: 0px;
margin: 0px;
font-size: 14px;
}
.centered
{
margin-left: auto;
margin-right: auto;
}
There's not going to be much to see here. We first need to add some PHP. The first line we add is the variable
name. If there is a parameter by the name of, well,
name, in the URL, use that value. If not, just use the string "Human Being".
index.php<?php
$name = (isset($_GET["name"]) ? $_GET["name"] : "Human Being");
?>
<!DOCTYPE html>
<html>
<head>
<title>Xmas 2023</title>
<link rel="stylesheet/less" type="text/css" href="css/styles.less" />
<script src="js/less.min.js"></script>
</head>
<body>
<div class="card">
<div class="image">
</div>
<div class="greeting">
<h1></h1>
<p></p>
</div>
<div style="clear: both"></div>
</div>
</body>
</html>
Then we have an array,
themes. It has three elements, each of them an array with keys. The
name key values have been provided. The rest are right now empty strings.
index.php<?php
$name = (isset($_GET["name"]) ? $_GET["name"] : "Human Being");
$themes = [
["name" => "snow", "title" => "", "prompt" => ""],
["name" => "food", "title" => "", "prompt" => ""],
["name" => "nativity", "title" => "", "prompt" => ""],
];
?>
Here, I've filled in the other values.
title is what is going to appear as a header in your eventual output. These strings use the variable
name.
prompt is what we will be using later, to get content.
index.php<?php
$name = (isset($_GET["name"]) ? $_GET["name"] : "Human Being");
$themes = [
["name" => "snow", "title" => "Seasons Greetings for a White Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 80 to 100 words, as a greeting on a Christmas Card, involving snow and winter"],
["name" => "food", "title" => "Dear " . $name . ", wishing you festive food and fun!", "prompt" => "Generate a short poem, using less than 100 words, as a greeting on a Christmas Card, revoving around food"],
["name" => "nativity", "title" => "Have a blessed Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 50 to 100 words, as a greeting on a Christmas Card, involving Jesus and the Nativity"]
];
?>
And then we use the
rand() function to define the variable
index as a value from 0 to 2. Then we define
content as the
prompt key value of the element of
themes referenced by the value of
index. Thus every time the page is reloaded, a different theme is used!
index.php<?php
$name = (isset($_GET["name"]) ? $_GET["name"] : "Human Being");
$themes = [
["name" => "snow", "title" => "Seasons Greetings for a White Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 80 to 100 words, as a greeting on a Christmas Card, involving snow and winter"],
["name" => "food", "title" => "Dear " . $name . ", wishing you festive food and fun!", "prompt" => "Generate a short poem, using less than 100 words, as a greeting on a Christmas Card, revoving around food"],
["name" => "nativity", "title" => "Have a blessed Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 50 to 100 words, as a greeting on a Christmas Card, involving Jesus and the Nativity"]
];
$index = rand(0, 2);
$content = $themes[$index]["prompt"];
?>
However, since we're at the design stage, we hardcode the value of
index at 0.
index.php<?php
$name = (isset($_GET["name"]) ? $_GET["name"] : "Human Being");
$themes = [
["name" => "snow", "title" => "Seasons Greetings for a White Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 80 to 100 words, as a greeting on a Christmas Card, involving snow and winter"],
["name" => "food", "title" => "Dear " . $name . ", wishing you festive food and fun!", "prompt" => "Generate a short poem, using less than 100 words, as a greeting on a Christmas Card, revoving around food"],
["name" => "nativity", "title" => "Have a blessed Christmas, " . $name . "!", "prompt" => "Generate a short paragraph, between 50 to 100 words, as a greeting on a Christmas Card, involving Jesus and the Nativity"]
];
$index = rand(0, 2);
$index = 0;
$content = $themes[$index]["prompt"];
?>
In the HTML, add in the PHP code to display title strings and content.
index.php<!DOCTYPE html>
<html>
<head>
<title>Xmas 2023</title>
<link rel="stylesheet/less" type="text/css" href="css/styles.less" />
<script src="js/less.min.js"></script>
</head>
<body class="theme_<?php echo $themes[$index]["name"]; ?>">
<div class="card">
<div class="image">
</div>
<div class="greeting">
<h1><?php echo $themes[$index]["title"]; ?></h1>
<p><?php echo $content; ?></p>
</div>
<div style="clear: both"></div>
</div>
</body>
</html>
If you were to run the code now, it would look like this. This is in dire need of styling.
We'll do it in the LESS file. Start by creating a style called
theme_snow. That's the one that is currently active because we hardcoded the value of
index to 0. While we're at it, create classes for
theme_food and
theme_nativity.
css/styles.lesshtml, body
{
height: 100%;
padding: 0px;
margin: 0px;
font-size: 14px;
}
.centered
{
margin-left: auto;
margin-right: auto;
}
.theme_snow
{
}
.theme_food
{
}
.theme_nativity
{
}
In here, we want to set the font and the background to a deep
blue.
css/styles.less.theme_snow
{
font-family: arial;
background: rgb(0, 0, 100);
}
Now we want to style
card within
theme_snow. In this case,
card will be a translucent
white rectangle in the middle of the screen, with rounded corners. We'll use
centered here, which we defined earlier.
css/styles.less.theme_snow
{
font-family: arial;
background: rgb(0, 0, 100);
.card
{
margin-top: 10px;
width: 600px;
height: 650px;
padding: 2em;
border-radius: 10px;
.centered;
background: rgba(255, 255, 255, 0.5);
}
}
We then style image. It will be circular and it will use the snowman image as its background. Again, it is in the middle of its parent, so use
centered.
css/styles.less.theme_snow
{
font-family: arial;
background: rgb(0, 0, 100);
.card
{
margin-top: 10px;
width: 600px;
height: 650px;
padding: 2em;
border-radius: 10px;
.centered;
background: rgba(255, 255, 255, 0.5);
}
.image
{
width: 250px;
height: 250px;
border-radius: 50%;
margin-bottom: 10px;
background-image: url(../img/snow.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
.centered;
}
}
Finally, we style
greeting. It will have
white text, and take the full width and a certain height.
css/styles.less.theme_snow
{
font-family: arial;
background: rgb(0, 0, 100);
.card
{
margin-top: 10px;
width: 600px;
height: 650px;
padding: 2em;
border-radius: 10px;
.centered;
background: rgba(255, 255, 255, 0.5);
}
.image
{
width: 250px;
height: 250px;
border-radius: 50%;
margin-bottom: 10px;
background-image: url(../img/snow.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
.centered;
}
.greeting
{
width: 100%;
height: 350px;
color: rgb(255, 255, 255);
}
}
Refresh. Quite a drastic change, ain't it?
Back to the PHP, change the value of index.
index.php$index = rand(0, 2);
$index = 1;
And now we will work on the CSS class
theme_food. As before, we set the font and change the background color to a deep
red.
css/styles.less.theme_food
{
font-family: verdana;
background: rgb(150, 0, 0);
}
The
card styling here is another rectangle, also centered using
centered, and it's an opaque
cream color. We use
box-shadow to give this card a translucent
black shadow.
css/styles.less.theme_food
{
font-family: verdana;
background: rgb(150, 0, 0);
.card
{
margin-top: 10px;
width: 800px;
height: 600px;
padding: 1em;
.centered;
background: rgb(200, 200, 100);
box-shadow: 10px 10px rgba(0, 0, 0, 0.5);
}
}
For
image, we are going to float it left and make it a tall rectangle. Then we are going to make
food.jpg its background.
css/styles.less.theme_food
{
font-family: verdana;
background: rgb(150, 0, 0);
.card
{
margin-top: 10px;
width: 800px;
height: 600px;
padding: 1em;
.centered;
background: rgb(200, 200, 100);
box-shadow: 10px 10px rgba(0, 0, 0, 0.5);
}
.image
{
width: 50%;
height: 100%;
float: left;
background-image: url(../img/food.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
}
For
greeting, we will float it right.
css/styles.less.theme_food
{
font-family: verdana;
background: rgb(150, 0, 0);
.card
{
margin-top: 10px;
width: 800px;
height: 600px;
padding: 1em;
.centered;
background: rgb(200, 200, 100);
box-shadow: 10px 10px rgba(0, 0, 0, 0.5);
}
.image
{
width: 50%;
height: 100%;
float: left;
background-image: url(../img/food.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
.greeting
{
width: 45%;
height: 100%;
float: right;
}
}
And the final result is...
Great. Time to work on the final theme,
theme_nativity. This one is slightly different in the sense that
image and
greeting are not next to each other, but occupy the same space. They intersect.
First, change the value of
index to 2.
index.php
$index = rand(0, 2);
$index = 2;
Define font and background for
theme_nativity. Let' go for
beige.
css/styles.less.theme_nativity
{
font-family: georgia;
background: rgb(150, 100, 50);
}
card is going to be a large rectangle, with no defined background, and a thick
brown border. Again, we use
centered to center it - bet you're glad we're using LESS now!
css/styles.less.theme_nativity
{
font-family: georgia;
background: rgb(150, 100, 50);
.card
{
margin-top: 50px;
width: 800px;
height: 600px;
.centered;
border: 1em solid rgb(50, 0, 0);
}
}
We will use
image to fill up the whole of card. For this, we set the
position property to absolute and use
nativity.jpg as the background image.
css/styles.less
.theme_nativity
{
font-family: georgia;
background: rgb(150, 100, 50);
.card
{
margin-top: 50px;
width: 800px;
height: 600px;
.centered;
border: 1em solid rgb(50, 0, 0);
}
.image
{
width: 800px;
height: 600px;
position: absolute;
background-image: url(../img/nativity.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
}
Here, greeting will be a translucent
black box with
white text and rounded corners, set right in the middle of
image. Again,
position will be set to
absolute for this to happen. The
margin-left and
margin-top properties are a function of the width and height of
greeting compared to the width and height of
image.
css/styles.less.theme_nativity
{
font-family: georgia;
background: rgb(150, 100, 50);
.card
{
margin-top: 50px;
width: 800px;
height: 600px;
.centered;
border: 1em solid rgb(50, 0, 0);
}
.image
{
width: 800px;
height: 600px;
position: absolute;
background-image: url(../img/nativity.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
.greeting
{
width: 400px;
height: 300px;
position: absolute;
margin-left: 200px;
margin-top: 150px;
padding: 1em;
background-color: rgba(0, 0, 0, 0.8);
color: rgb(255, 255, 255);
border-radius: 5px;
}
}
We'll even add in some stying for h1 for shits and giggles. I want it to be in italics.
css/styles.less.theme_nativity
{
font-family: georgia;
background: rgb(150, 100, 50);
.card
{
margin-top: 50px;
width: 800px;
height: 600px;
.centered;
border: 1em solid rgb(50, 0, 0);
}
.image
{
width: 800px;
height: 600px;
position: absolute;
background-image: url(../img/nativity.jpg);
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
h1
{
font-style: italic;
font-size: 1.5em;
text-align: center;
}
.greeting
{
width: 400px;
height: 300px;
position: absolute;
margin-left: 200px;
margin-top: 150px;
padding: 1em;
background-color: rgba(0, 0, 0, 0.8);
color: rgb(255, 255, 255);
border-radius: 5px;
}
}
Neat!
This didn't take long at all. We've managed to create styles for three different themes with radically different layouts, through the power of LESS.
Next
Filling in the text using
ChatGPT.