i decided to make this tutorial to teach you how to program in javascript. wait wait! don't run away yet! i know that coding might feel scary or often is used to make websites slow and bloated, but it doesn't have to be that way!
at the end, we're going to use this to make an interactive web stamp that reacts to moving the mouse
to get started, i'm going to assume a basic familiarity with code as a concept, but you don't have to know any javascript. if you've done some intermediate-level html+css, or if you've used something like Scratch, that should be good enough. i'm going to explain everything as we go along
i strongly recommend a computer (or at least something with a physical keyboard) for this, but a phone technically works too
once again, we're going to be using mozilla's playground: https://developer.mozilla.org/en-US/play
> beginner code <
if you've written code before and know about syntax and variables, feel free to skip this section
the first line of code you will want to write is: console.log("Hello, world!");
put this into the box labeled "JavaScript", wait for the page to refresh, and look in the "Console". some text will show up there.
the bit inside the quotation marks is called a "string", and it's how you put text into your program. this is just like using quotation marks in css, or in html attributes. you can change this string to something else, and the computer remembers what you put there, but the computer is dumb and doesn't know anything else about it. it only does exactly what you tell it to do
what we're telling the computer to do is to run "console.log". this is called a "function call". think of a function like a machine (or a factory) that you can put stuff (inputs) into. here, we're putting "Hello, world!" (or "farts") into "the console.log machine". you don't have to know how this works inside, so you can focus your attention on what it does for you. as an analogy, think about how you don't have to know how a recycling plant works, you just have to know that you give them your paper and plastic to be recycled
to call a function, you use () parentheses symbols. if there is more than one input, you separate them with commas (there's only one input here, so we don't have a comma)
at the end of every line, i recommend that you write a ; semicolon. this tells the computer "this step is finished. now we're on to the next step." if you don't tell the computer this, javascript will try to guess where each step ends. it uses some rules to guess, but i can never remember what they are. unless you want the computer to keep guessing what you mean, tell it what you mean explicitly. remember, computers are dumb. you are smart.
finally, one more thing you absolutely need to know before we can do something interesting: variables
when we write the word "let", it tells the computer to create a variable. "let" is an example of a keyword, a word which has special meaning to the computer. (if you've seen older tutorials, they often use "var" instead. the difference between "var" and "let" is very complicated and we won't go over it now, but they both create variables)
a variable is basically a place for the computer to put some information. except, we've stuck a label on it. imagine a box with "x" written on it in sharpie. inside this box, we've put a piece of paper with "Hello, world!" written on it
after creating this variable, the computer moves on to the next step (remember? semicolon ; !). in this next step, we take what's inside the variable "x" and give it to the "console.log" function
except, in the analogy, we actually make a copy of the piece of paper. the box still has another copy inside of it. this is also really complicated (values vs references), and so once again we're going to skip over it for now
in the last line, we add "x" to "x" and then put that into "console.log". in javascript, we can add strings to strings, not just numbers like in math. when we do that, it joins them together. this is why the console shows "Hello, world!Hello, world!"
notice that there isn't a space between the two copies! the computer does exactly what we told it to do, and we didn't tell it to put a space, and so it didn't
> canvas <
we now need to go back to html real quick and add a <canvas> element, like this: <canvas id="canvas" width="400px" height="200px"></canvas>
in the javascript, write this: let canvas = document.getElementById("canvas"); console.log(canvas);
we don't see anything on the page, but the console should show some output like [object HTMLCanvasElement]
what we're doing here is that we took "canvas" and gave it to the "document.getElementById" function. that function gave us back an output, and we put that output into the "canvas" variable
imagine you have an assistant that you ask "please go into the page, and find me the element with id 'canvas' ". this assistant wanders off, rummages around, eventually finds the canvas, and gives it back to you. you don't have to know where or how that happened, you just know that your assistant found what you were looking for
finally finally finally, we're finally getting somewhere! replace the console.log (which we only needed for testing) with this:
let draw = canvas.getContext('2d');
draw.fillRect(10, 10, 20, 30);
we've made a rectangle!
you might be wondering... what on earth was the point of all that? that was so much work, it'd be easier to open mspaint and draw a rectangle by hand!
and you're right! this here is a big problem with learning to code. it takes a ton of work to even get started. the point of code, though, is that computers are really good at doing things repeatedly, very fast, and without getting bored:
this code uses a "for loop", which is a special set of instructions to tell the computer "do this repeatedly"
we're not going to use for loops in the rest of this tutorial, so go look it up on your own!
> saving the output <
i don't know about any other browsers, but at least in firefox on desktop, you can right-click on the canvas to save it as a PNG. it automatically saves with transparency too!
> adding interactivity <
here, we're going to add interactivity to our page. replace the fillRect line with the following code:
now, move your mouse over the canvas and watch what happens! (you can't move the mouse if you're on a phone, but you can tap on the canvas to make little squares)
two important concepts that need to be explained here
first of all, when you write something.somethingElse, the "somethingElse" is called a property which belongs to "something"
this means that we're telling the "document" (a variable which magically exists and refers to the whole page) to find ("getElementById") for us the "canvas" element. then we're asking the canvas for the ability to draw 2d. and then we also ask the canvas to add an event listener to detect when the mouse is moving. inside of that (inside the curly braces {} ), we tell "draw" to fill in a rectangle
the second thing is that (e) => { ... } syntax. this is called an arrow function and is one of the ways to create brand-new functions of our own. when the mouse moves, the browser takes information about the mouse (what we've called "e") and calls our function with it. this happens again and again whenever the mouse keeps moving
> bugs, and debugging <
unfortunately, our code currently has a problem (what programmers call "bugs"). if we, for example, add some stuff to the page above the canvas, this happens:
unfortunately, the x and y coordinates that we get from mouse events is relative to the page, not to the element. it was only working correctly before because the canvas was in the corner.
this is okay! don't panic!
we need to copy-paste this code to fix it:
let mouse_x = e.x - e.currentTarget.offsetLeft;
let mouse_y = e.y - e.currentTarget.offsetTop;
draw.fillRect(mouse_x, mouse_y, 10, 10);
this code subtracts the position of the canvas from the position of the mouse, which gives us the mouse position relative to the canvas
also, in case we don't want to keep all previous squares, we can use clearRect:
by now we've already made two simple programs! a really basic drawing program, and a program where something follows the mouse around
> migrating to neocities <
before we can move on to making the stamp I promised at the beginning, we should put our code on a real web host like neocities. this is because we're going to want to be able to upload our own images
for now, create a new page (or open an existing page for editing). copy the html canvas element into the page, and then (this is really important!) at the end of the page, right before you write </body>, write <script></script>
then copy-paste your javascript between the script tags. it should look like this
now if you view your new page you should see the same square following the mouse cursor. except now it's on your page!
> interactive web stamp <
as promised, something to tie all this together
in your neocities dashboard, upload a stamp base image and an image to draw on top. we're going to be using the following two images here:
it should look something like this in your dashboard
now, inside your html, inside a <div> tag, add two <img> tags to load these images. later on in the javascript we'll use these images
for testing, refresh your page and make sure that the images load
we don't want these images to actually show up like this, but we're required to put them in <img> tags (because the rules say so), so to get around this we add style="display: none" to the div to hide them
now, inside our javascript, we want to use document.getElementById again:
// Get the images we want to draw with
let stamp = document.getElementById("stamp");
let shyguy = document.getElementById("shyguy");
and finally, change the canvas size to the usual web stamp size, 99px by 56px
make sure your code looks like this:
now visit your page, and move the mouse around over the canvas! you now have a stamp, but it moves!
> final bug <
right now the stamp appears blank until you move the mouse for the first time. to fix that, we want to draw the images one time when they finish loading. to do that, we add this code:
// Draw the images when the page finishes loading addEventListener("load", () => {
draw.drawImage(stamp, 0, 0);
draw.drawImage(shyguy, 16, 10)
});
and now you have a debugged web stamp!
> going further <
maybe try changing the code to draw the shy guy layer centered around the mouse instead of to the bottom-right
try adding more effects
see if you can figure out how to respond to mouse clicks
don't be afraid to look things up or ask for help! happy hacking!
please say thanks if you liked it! please please also tell me if there's something you didn't understand, so that i can learn to get better at explaining!
this is a tutorial about how to make dividers for your own website (neocities, nekoweb, etc.) without needing a gif editor. it works best for simple shapes and patterns, but maybe you're more creative with it than me 😅
all the Big websites use techniques like this, but they only use them to make boring websites. why should they get all the fun?
to start with, i'm going to assume that you already know how to create an account with a web host, and that you know how to edit files and the basics of html and css. there are a lot of other tutorials for this if you don't!
i strongly recommend a computer (or at least something with a physical keyboard) for this, but a phone technically works too
anyways, let's get started!
first of all, i like to do most of my initial testing on Mozilla's playground: https://developer.mozilla.org/en-US/play . this website is free, doesn't need an account, and allows you to quickly try out html, css, and javascript, and you don't have to worry about <head>, <link rel="stylesheet">, or things like that. it automatically puts all of that stuff in for you. it also automatically refreshes the page as you type. (and the editor also has better autocomplete than neocities...)
> SVG <
the first thing i'm going to show you is SVG, or "Scalable Vector Graphics". this is a language, kinda like html, for describing images made out of shapes
if you've used inkscape, it makes svgs. but you can also make svgs entirely by hand
anyways, the most basic svg you can make is something like this: <svg width="16" height="16"></svg>
but the problem with this is that an svg is completely transparent by default, so you won't actually see anything!
for testing, i like to put this into the css box: svg { background-color: black; }
it's perfectly okay to write some code like this that only gets used for testing, and that you'll throw away later! (maybe say thank you to the code for helping you along the way?)
if you did it right, your code should look like this. see that small black square?
we're now going to put a white circle inside our svg: <circle cx="8" cy="8" r="6" fill="white"/>
make sure you have that little / symbol! the rules for svg are slightly different from html, and we need this to tell the computer that there's no more tags inside the circle
finally, the next steps will require us to uglify this code :pout:
inside the <svg> tag, right after "<svg", we need to write exactly this (just copy-paste it): xmlns="http://www.w3.org/2000/svg"
and finally, we need to delete all the new lines so that everything is on a single line. it should look like this when you're done
now copy-paste this code and save it in a note somewhere. we're going to need it later, but for now we need to clear out all our code and start over
> basic CSS divider <
we can make a basic divider by creating a <div> with a class, and then styling it with CSS. you don't have to write any text inside the <div>. we'll just be giving it a height using css. start with this:
.divider {
height: 16px;
background-color: red;
}
you should get something that looks like this:
now time for the best trick
> mask-image <
there is a css property called "mask-image" that basically tells the browser to overlay an image on top of an element. this is a new feature from around 2023
to think about it, imagine having the element on a piece of paper and cutting out parts of it with scissors. you keep only the parts that are colored white in the mask image (this is why we made the circle white earlier)
to use mask-image, we need to give it the URL of an image we want to use as a mask. but here the image we want to use is that small SVG we created earlier. it seems silly to make a whole entire separate file for that, doesn't it?
we can solve this using "data URLs". what this does is that it tells the browser "instead of downloading something, i already just put the contents right here in front of you"
to start with, copy-paste the following into your css: mask-image: url('data:image/svg+xml,');
this is a basic data url that tells the browser "i'm going to be giving you an svg". but we haven't actually put in the svg yet. remember how i told you to save the svg in a note somewhere? now we're going to need that. take that svg and copy-paste it after the comma
boom, like magic, we now have a simple divider!
> SVG paths <
instead of a circle, i'm going to be using a svg path instead: <path stroke-width="3" stroke="white" d="M0 0 L16 16 M16 0 L0 16"/>
path is an svg element that gives you a "pen" that you can move, put down, and draw lines and curves with. if you've done programming using "that turtle", it's basically the same idea. this language uses those letter and number symbols inside the "d" attribute. "M" means "move to" and L means "draw a line to"
you can find more information on the internet: https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/d#path_commands
you can also draw paths using other software and then copy-paste the code instructions, but that's super-advanced mode
the path i'm using draws an X shape out of two lines. each line is 3 pixels wide
> CSS animation <
now comes the part where we finally get to animate things!
the first thing you're going to need to know about is css keyframe blocks. we're going to be using this code here:
@keyframes slide-across {
from { mask-position: 0px 0px; }
to { mask-position: 16px 0px; }
}
this means that we're going to be moving the mask image from being shifted by 0 pixels all the way to being shifted by 16 pixels (and then it loops)
this goes *outside* of the block for the divider class!
to use it, *inside* the divider class we write: animation: 0.4s linear 0s infinite slide-across;
your code should look like this
if you did everything right, you'll see the divider scrolling!
> changing the color <
you can also change the background color using css animation! to do that, we create another set of keyframes. inside it, we can use "filter: hue-rotate(360deg);"
to add this animation to the divider, replace the semicolon ; with a comma, and then copy-paste the animation instructions a second time. make sure you change "slide-across" to "color-change"
congratulations!! you now have a color-changing, scrolling divider
Putting it on Neocities
go to your neocities dashboard and open your css in the editor. if you're using the default template, this means you need to edit style.css. on my website, i've made a duplicate copy of style.css called test.css, so i'll be editing that instead
with the default template, you'll have some code like this
go back to the mdn playground, select all your css (press Ctrl-A on desktop), and copy-paste it at the end
make sure you hit save! now open index.html (or whatever file you want to edit)
wherever you want a divider, you can write <div class="divider"></div>
you can do this as many times as you want! for example:
again, make sure you save! now if you go view your site, you should see a divider there!
and just to show you that you can do it as many times as you like:
> advanced <
you can put more than just a from and to in your animations:
and you can change the way the animation plays (the "easing" function)
bouncy!
if you're using firefox on desktop, there is even an editor for easing functions in the developer tools:
anyways, i really hope this helped something! please say thanks if you liked it! please please also tell me if there's something you didn't understand, so that i can learn to get better at explaining!
this is a tutorial about how to make dividers for your own website (neocities, nekoweb, etc.) without needing a gif editor. it works best for simple shapes and patterns, but maybe you're more creative with it than me 😅
all the Big websites use techniques like this, but they only use them to make boring websites. why should they get all the fun?
to start with, i'm going to assume that you already know how to create an account with a web host, and that you know how to edit files and the basics of html and css. there are a lot of other tutorials for this if you don't!
i strongly recommend a computer (or at least something with a physical keyboard) for this, but a phone technically works too
anyways, let's get started!
first of all, i like to do most of my initial testing on Mozilla's playground: https://developer.mozilla.org/en-US/play . this website is free, doesn't need an account, and allows you to quickly try out html, css, and javascript, and you don't have to worry about <head>, <link rel="stylesheet">, or things like that. it automatically puts all of that stuff in for you. it also automatically refreshes the page as you type. (and the editor also has better autocomplete than neocities...)
> SVG <
the first thing i'm going to show you is SVG, or "Scalable Vector Graphics". this is a language, kinda like html, for describing images made out of shapes
if you've used inkscape, it makes svgs. but you can also make svgs entirely by hand
anyways, the most basic svg you can make is something like this: <svg width="16" height="16"></svg>
but the problem with this is that an svg is completely transparent by default, so you won't actually see anything!
for testing, i like to put this into the css box: svg { background-color: black; }
it's perfectly okay to write some code like this that only gets used for testing, and that you'll throw away later! (maybe say thank you to the code for helping you along the way?)
if you did it right, your code should look like this. see that small black square?
we're now going to put a white circle inside our svg: <circle cx="8" cy="8" r="6" fill="white"/>
make sure you have that little / symbol! the rules for svg are slightly different from html, and we need this to tell the computer that there's no more tags inside the circle
finally, the next steps will require us to uglify this code :pout:
inside the <svg> tag, right after "<svg", we need to write exactly this (just copy-paste it): xmlns="http://www.w3.org/2000/svg"
and finally, we need to delete all the new lines so that everything is on a single line. it should look like this when you're done
now copy-paste this code and save it in a note somewhere. we're going to need it later, but for now we need to clear out all our code and start over
> basic CSS divider <
we can make a basic divider by creating a <div> with a class, and then styling it with CSS. you don't have to write any text inside the <div>. we'll just be giving it a height using css. start with this:
.divider {
height: 16px;
background-color: red;
}
you should get something that looks like this:
now time for the best trick
> mask-image <
there is a css property called "mask-image" that basically tells the browser to overlay an image on top of an element. this is a new feature from around 2023
to think about it, imagine having the element on a piece of paper and cutting out parts of it with scissors. you keep only the parts that are colored white in the mask image (this is why we made the circle white earlier)
to use mask-image, we need to give it the URL of an image we want to use as a mask. but here the image we want to use is that small SVG we created earlier. it seems silly to make a whole entire separate file for that, doesn't it?
we can solve this using "data URLs". what this does is that it tells the browser "instead of downloading something, i already just put the contents right here in front of you"
to start with, copy-paste the following into your css: mask-image: url('data:image/svg+xml,');
this is a basic data url that tells the browser "i'm going to be giving you an svg". but we haven't actually put in the svg yet. remember how i told you to save the svg in a note somewhere? now we're going to need that. take that svg and copy-paste it after the comma
boom, like magic, we now have a simple divider!
> SVG paths <
instead of a circle, i'm going to be using a svg path instead: <path stroke-width="3" stroke="white" d="M0 0 L16 16 M16 0 L0 16"/>
path is an svg element that gives you a "pen" that you can move, put down, and draw lines and curves with. if you've done programming using "that turtle", it's basically the same idea. this language uses those letter and number symbols inside the "d" attribute. "M" means "move to" and L means "draw a line to"
you can find more information on the internet: https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/d#path_commands
you can also draw paths using other software and then copy-paste the code instructions, but that's super-advanced mode
the path i'm using draws an X shape out of two lines. each line is 3 pixels wide
> CSS animation <
now comes the part where we finally get to animate things!
the first thing you're going to need to know about is css keyframe blocks. we're going to be using this code here:
@keyframes slide-across {
from { mask-position: 0px 0px; }
to { mask-position: 16px 0px; }
}
this means that we're going to be moving the mask image from being shifted by 0 pixels all the way to being shifted by 16 pixels (and then it loops)
this goes *outside* of the block for the divider class!
to use it, *inside* the divider class we write: animation: 0.4s linear 0s infinite slide-across;
your code should look like this
if you did everything right, you'll see the divider scrolling!
> changing the color <
you can also change the background color using css animation! to do that, we create another set of keyframes. inside it, we can use "filter: hue-rotate(360deg);"
to add this animation to the divider, replace the semicolon ; with a comma, and then copy-paste the animation instructions a second time. make sure you change "slide-across" to "color-change"
congratulations!! you now have a color-changing, scrolling divider
Putting it on Neocities
go to your neocities dashboard and open your css in the editor. if you're using the default template, this means you need to edit style.css. on my website, i've made a duplicate copy of style.css called test.css, so i'll be editing that instead
with the default template, you'll have some code like this
go back to the mdn playground, select all your css (press Ctrl-A on desktop), and copy-paste it at the end
make sure you hit save! now open index.html (or whatever file you want to edit)
wherever you want a divider, you can write <div class="divider"></div>
you can do this as many times as you want! for example:
again, make sure you save! now if you go view your site, you should see a divider there!
and just to show you that you can do it as many times as you like:
> advanced <
you can put more than just a from and to in your animations:
and you can change the way the animation plays (the "easing" function)
bouncy!
if you're using firefox on desktop, there is even an editor for easing functions in the developer tools:
anyways, i really hope this helped something! please say thanks if you liked it! please please also tell me if there's something you didn't understand, so that i can learn to get better at explaining!