Reel Memories: Adding Vintage Film Effects with HTML & CSS
Let's take your web design back in time to the golden age of vintage film! Using the power of HTML and CSS, we'll create an epic Vintage Film Effect that'll leave your viewers speechless. So grab your coding tools, and let's bring this old-school magic to life!
HTML Code :
First, we are gonna create a Boilerplate for the HTML Code & link it with the CSS file.
Now inside the body tag, we're gonna start with two checkboxes, each with an "id" attribute of "invert" and "sepia". These checkboxes are used to control certain visual effects on a piece of content, which we'll get to in a moment.
Following the checkboxes, there is a "div" element with a class of "content". This is simply a container for our content, which will be affected by the checkboxes.
Within the "content" div, we have another "div" element with a class of "film". This is also just a container for our content, but it has a visual effect applied to it.
Finally, within the "film" div, we have another "div" element with a class of "effect". This is where the magic happens. Depending on which checkbox is selected, this div will apply a visual effect to its content.
If the "invert" checkbox is selected, the "effect" div will apply an "invert" effect, which will essentially invert the colors of the content within it.
If the "sepia" checkbox is selected, the "effect" div will apply a "sepia" effect, which will give the content a nostalgic, old-timey look.
To add even more visual interest, the "effect" div also contains a "grain" div, which adds a subtle grainy texture to its content.
So with just a bit of code, we can create interactive and visually interesting content. Don't be afraid to experiment and see what other effects you can create with just a few lines of code.
The output of the HTML Code :
The output will print a blank white page with 2 checkboxes on it.
Now let's add some CSS to style the page, make the image appear & later on add some filters to it.
CSS Code :
We're gonna start by creating a root selector. It's a special selector that allows us to define global CSS variables that can be used throughout the page. Inside this, we're defining two variables:
Then we're gonna use the *:before and *:after pseudo-elements to create some interesting visual effects.
In there, we're gonna set the position property to absolute for all elements on the page, including the * selector, which targets all elements. The *:before and *:after selectors are pseudo-elements that allow us to add content before or after an element.
By setting the position to absolute, we can position the *:before and *:after pseudo-elements relative to the nearest positioned ancestor. This can create some interesting effects, such as adding an overlay or a decorative element to an existing element.
Using pseudo-elements can add some creativity to our CSS styling and allow us to create unique effects on the page.
Then we're gonna style the body element. Inside that, we're gonna set the margin and padding of the body element to 0, effectively removing any extra space around the content. The width and height properties are set to 100vw and 100vh, respectively, which means that the body element will take up the full width and height of the viewport.
The overflow property is set to hidden, which means that any content that extends beyond the dimensions of the body element will be hidden. This can be useful for creating visual effects and controlling the layout of the page.
The display property is set to flex, which enables us to create flexible layouts and align elements within the body element. The align-items and justify-content properties are set to center, which will center the content both vertically and horizontally within the body element.
The background property is set to a variable named --black, which is defined in the root selector. This variable is used to set the background color of the body element to black.
Finally, the perspective property is set to 100vmin, which enables 3D transformation on the page. This can create some interesting effects and add depth to the page.
Then we're gonna set up the main content section of the webpage. We're gonna set the width and height of the section to be the size of the entire viewport and make sure that everything inside the section stays contained within its bounds. It also aligns the content inside the section both vertically and horizontally to the center.
Additionally, we're gonna set a background image for the section that covers the entire area of the section without distortion. Finally, it applies a transition effect to the section's changes for a smooth and elegant visual effect.
Here is a detailed explanation:
Next, we're gonna add two pseudo-elements, :before and :after, to the previously defined .content container. The :before pseudo-element adds a text description or caption to the container, while the :after pseudo-element adds a box shadow effect to the container.
Here is a detailed explanation:
Then we're gonna create a shadow effect on the element with the class .content. Specifically, it creates a shadow that appears to be inset into the element, rather than around it.
The :after part of the code is used to create a new element that appears after the content of the .content element. This new element is transparent, so it doesn't have any visible content.
The width and height properties set the dimensions of the new element to be the same as the .content element, so it completely covers the original content.
The box-shadow property is used to create the shadow effect. The first set of values (0 0 20vmin 0vmin var(--black) inset) creates a large, soft shadow that appears around the edges of the element.
The second set of values (0 0 3vmin 0.5vmin var(--black) inset) creates a smaller, darker shadow that appears closer to the center of the element.
The third set of values (0 0 1vmin 1vmin var(--black)) creates a very small, bright shadow that appears in the center of the element.
Overall, we're creating a layered shadow effect on the .content element that can add visual interest to a web page.
Then we're gonna create a visual effect on elements with the .film, .effect classes by making them slightly blurred and adding a subtle drop shadow.
Here is a detailed explanation:
These effects can be useful in creating a more visually engaging user interface for a website or web application.
Then we're gonna target two elements that have the classes .film and .effect, respectively. For both elements, we are gonna create a pseudo-element called :after, which allows you to insert new content after the selected element.
The content property sets the content for the generated pseudo-element. In this case, it's an empty string, so nothing will be displayed in the pseudo-element.
The width and height properties set the dimensions of the pseudo-element to be 120% of the width of the parent element and 100% of its height. The top and left properties set the position of the pseudo-element to be at the top left corner of the parent element.
The padding-left property adds 100 pixels of padding to the left side of the pseudo-element, which creates space between the generated content and the left edge of the parent element.
The opacity property sets the transparency level of the pseudo-element to 0.5, making it partially transparent.
The animation property sets the animation effect
The background property sets the background color and gradient of the pseudo-element. It creates a repeating linear gradient that goes from black with 2% opacity to transparent. The gradient is set to repeat every 4 pixels and go up to 37% of the parent element's viewport height.
For the .effect:after pseudo-element, the left property is set to 30% instead of 0%, which means it will be positioned slightly to the right of the .film:after pseudo-element. Additionally, the animation property is set to effect-scratch, which has a longer duration of 2 seconds and also repeats infinitely.
Then we're gonna target an element with the class .grain. It sets the width and height properties of this element to be 100% of the width and height of its parent element, respectively.
The width property sets the width of the element, which in this case is set to 100% of its parent element's width. This means the element will stretch to fill the entire width of its parent element.
The height property sets the height of the element, which in this case is set to 100% of its parent element's height. This means the element will stretch to fill the entire height of its parent element.
Here we're ensuring that the element with the .grain class will take up the full width and height of its parent element. This can be useful for creating full-screen visual effects or for ensuring that a particular element is always the same size as its parent element, regardless of the size of the browser window.
Inside the .grain:after class, we're gonna set the content property of the pseudo-element to an empty string, which means no content is added after the main content of the element.
The width and height properties set the size of the pseudo-element to be 110% of the size of the element it is attached to. The top and left properties shift the pseudo-element up and to the left by 5% of the size of the element it is attached to, effectively creating a border around the main content of the element.
The opacity property sets the transparency of the pseudo-element to 0.25, which means it will be partially see-through.
The background-image property sets the background of the pseudo-element to two repeating conic gradients. A conic gradient is a type of gradient where the colors radiate from a central point, similar to a pie chart. The first conic gradient starts with the color var(--black) at 0% and becomes transparent as it moves toward the center of the element.
The second conic gradient starts with the color var(--black) at 0% and becomes transparent as it moves away from the center of the element.
Recommended by LinkedIn
The animation property sets an animation called grain to be applied to the pseudo-element. The grain animation lasts for 0.5 seconds and uses the steps(1) timing function, which means it jumps from one animation step to the next without any interpolation. The infinite value makes the animation repeat indefinitely.
Finally, the filter property applies a drop shadow to the pseudo-element. The drop shadow has no horizontal or vertical offset (0px 0px) and a blur radius of 1px, and the color of the shadow is black.
Now here we're creating a moving grainy effect on an element. The animation has a series of steps that define how the element should move over time.
Here's what each step does:
The animation then repeats infinitely, creating a continuous grainy effect on the element.
Then we're gonna create an effect of film scratches or texture over the image. It defines a sequence of styles that the element will go through over a period of time.
At the start and end of the animation (0% and 100%), the element is in its default state. It has opacity set to 0.5, which means it's somewhat transparent.
From 10% to 80%, the transform property moves the element horizontally on the X-axis. The translateX() function moves the element a certain percentage to the left or right, based on the value provided. For example, transform: translateX(-1%); moves the element 1% to the left.
As the element moves, the opacity property is also adjusted, which makes it appear to fade in and out. For example, at 30%, the opacity is increased to 0.75, which makes the scratches more visible.
By the end of the animation, the element has returned to its default state, with an opacity of 0.5 and no horizontal movement.
So here we're creating a subtle, flickering effect that mimics the look of an old film.
The "effect-scratch" effect can be used to create a visual effect of scratches on a surface, such as an old film or photograph.
By combining these steps, the animation creates the effect of a scratch or glitch on the element.
Some Options:
The --pos property is a custom property that allows developers to define a percentage value and use it in multiple places throughout their CSS code.
The syntax for the --pos property is <percentage>. This means that you can set any percentage value you like as the value for this property.
One important thing to note about the --pos property is that it does not inherit its value from any parent element. This means that if you set a value for --pos on one element, that value will only apply to that specific element and not to any of its children.
The initial value for --pos is set to 20%. This means that if you do not explicitly set a value for --pos on an element, it will default to a value of 20%.
The --pos property can be a very useful tool for web developers, allowing them to easily define a percentage value that can be reused throughout their code. Just remember that it does not inherit its value, so you will need to set it explicitly on each element you want to use it on.
Next, we're gonna hides any input element on the page, which means that it won't be visible or take up any space on the page.
In the next line of code, we're gonna position the label as absolutely, which means it's taken out of the normal flow of the document and can be placed anywhere on the page.
The background is set to a semi-transparent black color using an RGBA value, which is a way to specify a color with an alpha (opacity) value. The bottom of the label is positioned 7vmin from the bottom of the viewport, or browser window. The z-index property specifies the stacking order of the element; a higher value means it will be displayed on top of other elements with lower z-index values.
The width and height of the label are set using viewport units, which are a way to specify a length relative to the size of the viewport. The margin-left property positions the label 15vmin from the left side of the viewport. The border-radius property gives the label rounded corners.
The cursor property sets the type of cursor to be displayed when hovering over the label, indicating that it can be clicked. Finally, the border properties give the label a top and bottom border, with the bottom border being slightly lighter than the top border.
Then we're gonna create a selector named label[for="invert"]. This will target a label element with a for attribute equal to "invert". The rule margin-left: -15vmin; then sets the left margin of this label element to be 15 viewport units to the left of its initial position.
This is commonly used in conjunction with an input element of type "checkbox" with an id attribute equal to "invert". By associating this input element with the label using the for attribute, clicking on the label will toggle the input element's checked state.
The purpose of setting the left margin of the label element to a negative value is to move the element outside of its container's bounds, creating the appearance of a custom-styled checkbox without requiring the use of any images.
This is a common technique used in modern web design to create more flexible and accessible UI components.
Now we're gonna style the circular icon of the button.
The "label:before" is used to add a circular element before the label text. It specifies the width and height of the circle to be 4vmin (which means 4% of the viewport width and height), sets the background color to #CC945C (a shade of orange), and sets the content to an empty string, which means there is nothing inside the circle.
It also sets the border radius to 100%, which gives the circle a round shape, sets the box-sizing property to border-box, which tells the browser to include the border and padding within the circle's dimensions, and sets the position of the circle to be 0.5vmin from the top and 0.75vmin from the left. Finally, it adds a box-shadow effect, which creates a shadow behind the circle to give it a three-dimensional effect.
The "label:after" is used to add text after the label. It specifies the font family to be Arial, Helvetica, or any sans-serif font installed on the user's computer. It sets the font weight to 500, which means it's a medium-weight font, and the font size to 1.25vmin.
It sets the content to "SEPIA FILTER", which is the text that appears after the label. It sets the color to #fffd (a shade of white), the bottom position to 6.5vmin, and the background to a combination of linear and conic gradients.
The linear gradient creates a transition from black to a transparent white color, and the conic gradient creates a gradient that radiates out from a specific position. The "--pos" variable specifies the position of the gradient, and "--black" specifies the color of the gradient.
It also adds padding to the text, sets the text shadow to none, adds letter spacing to the text, sets the margin-left to 0, sets the opacity to 0.65 (which means it's somewhat transparent), sets the width to 100%, and sets the box-sizing to border-box. Finally, it centers the text using the text-align property and adds a transition effect using the "--transition" variable.
Next, we're gonna use the "label[for="invert"]" selector, which selects the label element with the "for" attribute set to "invert". This is typically used to associate the label with the corresponding input element.
After targeting the label element, we're gonna add a pseudo-element called ":after". This pseudo-element allows you to add content after the content of the selected element, in this case, the label element.
The "content" property specifies the text that will be displayed after the label element. In this case, it sets the content to "GRAIN FILTER".
Therefore, when a user clicks on the label associated with the input element with the "id" attribute set to "invert", the text "GRAIN FILTER" will be displayed after the label text.
This code is typically used in conjunction with JavaScript to create a custom user interface
So we're styling a label element associated with an input element with the "id" attribute set to "invert". When the user clicks on the label, the text "GRAIN FILTER" is displayed after the label text.
Button Checked:
Now we're gonna style the label element that comes immediately after a checked input element.
The code starts with "input:checked + label:before", which is a selector used to target the "before" pseudo-element of a label element. This "before" pseudo-element is positioned before the content of the label element and can be used to add decorative elements to the label.
The "+", which is called an adjacent sibling selector, is used to select the next element (in this case, the label element) that comes immediately after the checked input element.
When the associated input element is checked, the code sets the "left" property of the "before" pseudo-element to 7.25vmin. This moves the pseudo-element to the right by 7.25vmin from its original position.
The "transition" property specifies the duration of the transition effect, which is the time it takes for the pseudo-element to move from its original position to the new position.
Finally, we set the "background" property of the "before" pseudo-element to #E0BF9D. This changes the background color of the pseudo-element to a shade of beige.
So here we're creating a visual effect that styles a label element based on whether or not the associated input element is checked. When the input is checked, the label element moves to the right and changes its background color to a shade of beige.
Then we're gonna apply a Sepia filter to all elements with the class .content when the input with the ID sepia is checked. A Sepia filter is a visual effect that gives images a brownish tint, resembling old photographs. The value 0.75 in sepia(0.75) determines the strength of the effect. A higher value makes the image more sepia-toned.
Next, we're gonna invert the colors of all elements with the class .film inside an element with the class .content when the input with the ID invert is checked. Inverting the colors essentially switches all colors to their opposite value on the color wheel.
So, for example, black becomes white, and white becomes black. The value 1 in invert(1) means that the colors will be fully inverted. You can adjust this value between 0 and 1 to control the strength of the effect.
Lastly, we're gonna add a visual effect to the label of the input element when the input is checked. Specifically, we're gonna apply an animation called arrow to the ::after pseudo-element of the label.
The animation property specifies the name of the animation, its duration (0.5s), its timing function (ease), its delay (0s), and how many times it should repeat (1). The animation-fill-mode property tells the browser to keep the final state of the animation after it has finished playing. The transition property sets the transition effect between two states of an element.
Finally, the filter property applies the invert(1) filter, which inverts the colors of the ::after element.