so on my site i use freezeframe to pause gifs, which is great for stuff within the html itself. however, i have gifs in the css themes themselves that i have no idea how to make it so that you can pause/play them with a button press (preferably with having them start paused). i suppose i could just have no gifs in the background, but i wish i could make it an option instead. anyone have any idea how to make it so that i can have freezeframe affect my css? or if it's a separate process that's needed, how to do so? if it's impossible i understand that as well. i had a bit of success with using an :active class and having png stills of the gifs, but it broke when multiple themes got involved with my tinkering, so i scrapped it for the time being
css:root {
--primary-bg: #f8f8ff;
--secondary-bg: #DCDCDC;
--bg: url(/root/backgrounds/greyflowr.gif);
--button-bg: #838996;
--button-text: white;
--header-bg: url(/root/header/stars.gif);
--boxes-bg: url(/root/backgrounds/swirls.gif);
--main2-bg: url(/root/backgrounds/stripes.gif);
}
@font-face {
font-family: retro;
src: url(/root/fonts/retrocomp.ttf);
}
@font-face {
font-family: DS;
src: url(/root/fonts/DS.ttf);
}
* {
cursor: url('https://cdn.cursors-4u.net/previews/the-moon-482c66bd-32.webp') 32 32, auto !important;
}
body {
background: var(--bg);
font-family: monospace;
padding: 5px;
}
.container {
display: flex;
border: 1px solid black;
background: var(--secondary-bg);
text-align: center;
height: 800px;
overflow: hidden;
flex: 0 0 100%;
flex-flow: row wrap;
font-family: DS;
}
@media (max-width: 600px) {
.container {
flex-direction: column wrap;
flex: 100%;
overflow: auto;
}
}
@media all and (min-width: 600px) {
.aside { flex: 1 0 0; }
}
@media all and (min-width: 800px) {
.main { flex: 3 800px; }
.primary-div { order: 2; }
.main { order: 3; }
.secondary-div { order: 4; }
.header { order: 1; }
}
.header {
background: var(--header-bg);
width: 100%;
margin-top: 0px;
height: 150px;
}
.primary-div {
background: var(--secondary-bg);
overflow: auto;
scrollbar-width: none;
height: 625px;
flex-grow: 0;
padding: 5px;
text-align: left;
}
.main {
width: auto;
height: 700px;
text-align: center;
font-size: 20px;
overflow: auto;
scrollbar-width: none;
border: black 1px solid;
background: var(--primary-bg);
flex-grow: 1;
padding: 5px;
align-items: center;
}
.secondary-div {
background: var(--secondary-bg);
overflow: auto;
scrollbar-width: none;
height: 625px;
flex-grow: 0;
padding: 5px;
}
.main2 {
width: 90%;
height: 150px;
overflow: auto;
scrollbar-width: none;
background: var(--main2-bg);
border: 1px dotted black;
padding: 5px;
text-align: center;
}
.container2 {
display: flex;
flex-flow: row nowrap;
height: 35%;
overflow: hidden;
}
@media (max-width: 600px) {
.container2 {
flex-flow: column wrap;
flex: 100%;
overflow: auto;
}
}
.box1 {
flex: 1;
border: 1px dotted black;
background: var(--boxes-bg);
overflow: auto;
scrollbar-width: none;
padding: 5px;
}
.box1:first-child {
margin-right: 20px;
border: 1px dotted black;
background: var(--boxes-bg);
overflow: auto;
scrollbar-width: none;
padding: 5px;
}
table.tables {
width: 100%;
background-color: #F8F8FF;
border-collapse: collapse;
border-width: 2px;
border-color: #000000;
border-style: solid;
color: #000000;
}
table.tables td, table.tables th {
border-width: 2px;
border-color: #000000;
border-style: solid;
padding: 5px;
}
table.tables thead {
background-color: #D0D6F8;
}
h3 {
font-family: retro;
border: 1px solid black;
background: url(/root/backgrounds/snowAC.gif);
text-align: center;
}
button {
background: var(--button-bg);
color: var(--button-text);
border: 1px solid black;
}
ul {
list-style-image: url('/root/favicons/starshoot.gif');
}
a:link {
color: #778899;
text-decoration: none;
}
a:visited {
color: #536878;
text-decoration: none;
}
a:hover {
color: blue;
text-decoration: underline;
}
a:active {
color: red;
text-decoration: underline;
}
.marquee {
width: 90%;
height: 40px;
background: #8c92ac;
border: 1px dotted black;
white-space: nowrap;
overflow: hidden;
}
.marquee2 {
width: 90%;
height: 25px;
background: #8c92ac;
border: 1px dotted black;
white-space: nowrap;
overflow: hidden;
}
.marquee div {
padding-left: 50%;
display: inline-block;
animation: animate 25s linear infinite;
align-items: center;
}
.marquee2 div {
padding-left: 50%;
display: inline-block;
animation: animate 25s linear infinite;
align-items: center;
}
@keyframes animate {
100% {
transform: translate(-100%, 0);
}
}
.generator {
background: url(/root/backgrounds/stripes.gif);
height: 200px;
width: 350px;
border: 1px dotted black;
text-align: center;
color: black;
font-family: DS;
}
.generator button {
background: #3b444b;
border: 3px inset aliceblue;
color: #e5e4e2;
padding: .5em;
font-family: retro;
font-weight: bolder;
}
html / freezeframe<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>halcyon daze</title>
<link rel="icon" type="image/x-icon" href="/root/favicons/paw.gif">
<link id="theme-stylesheet" rel="stylesheet" href="/css/light.css">
<script src="https://iframe.chat/scripts/main.min.js"></script>
<script>class FreezeImages {
constructor(options = {}) {
// Set default params
this.selector = options.selector || "freeze"
this.imgCls = "ff-img";
this.canvasCls = "ff-canvas";
this.hover = (options.hover === true || options.hover === "true") ? true : false;
this.noCSS = (options.no_css === true || options.hover === "true") ? true : false;
this.smoothing = (options.smoothing === false) ? false : true;
// Finds all images with selector class and within elements with the selected class
// and creates list
const imgList = document.querySelectorAll(`img.${this.selector}, .${this.selector} img`);
this.imgList = imgList;
// Creates <style> tag for new elements
if (!this.noCSS) {
const style = document.createElement('style');
style.textContent = `
.ff-container {
display: inherit;
width: 7.5px;
}
.ff-container img,
.ff-container canvas {
align-self: start;
}
.ff-container.ff-hover:hover .ff-active {
position: absolute;
opacity: 0;
}
.ff-container.ff-hover:hover .ff-inactive {
position: static;
opacity: 1;
z-index: 1;
}
.ff-inactive {
position: absolute;
opacity: 0;
z-index: -99;
}
`;
document.head.appendChild(style);
}
// Loops through all images
for (const img of this.imgList) {
// Gives <img> the inactive class, which hides GIF by default
img.className = `${this.imgCls} ff-inactive`;
// Creates <canvas> of GIF and copies data of first frame of animation
let canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
canvas.className = `${this.canvasCls} ff-active`;
canvas.getContext('2d').imageSmoothingEnabled = this.smoothing;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
// Creates container that will hold both <img> and <canvas>
let wrapper = document.createElement("div");
wrapper.className = "ff-container";
if (this.hover) wrapper.classList.add("ff-hover");
// Inserts container with <img> and <canvas> where <img> originally was
img.parentNode.insertBefore(wrapper, img);
wrapper.appendChild(img);
wrapper.appendChild(canvas);
}
}
start() { // Starts animation
for (const img of this.imgList) {
img.className = `${this.imgCls} ff-active`;
img.nextSibling.className = `${this.canvasCls} ff-inactive`;
}
}
stop() { // Stops animation
for (const img of this.imgList) {
img.className = `${this.imgCls} ff-inactive`;
img.nextSibling.className = `${this.canvasCls} ff-active`;
}
}
toggle() { // Toggles animation based on current state
for (const img of this.imgList) {
let imgNewCls = (img.className.includes('ff-inactive')) ? "ff-active": "ff-inactive";
let canvasNewCls = (img.className.includes('ff-inactive')) ? "ff-inactive": "ff-active";
img.className = `${this.imgCls} ${imgNewCls}`;
img.nextSibling.className = `${this.canvasCls} ${canvasNewCls}`;
}
}
}
// Waits for page to finish loading
document.addEventListener("readystatechange", function () {
if (document.readyState === "complete") {
// Initialize script
const f = new FreezeImages (
{
selector: "freeze",
}
)
// Set event listeners for all buttons
for(const el of document.getElementsByClassName('play-gif')) {
el.addEventListener('click', () => f.start());
}
for(const el of document.getElementsByClassName('stop-gif')) {
el.addEventListener('click', () => f.stop());
}
for(const el of document.getElementsByClassName('toggle-gif')) {
el.addEventListener('click', () => f.toggle());
}
}
});</script>
</head>
<body>
<div class="container">
<header class="header"></header>
<aside class="primary-div">
<br>
<center>
<button onclick="lightmode()">light</button> -
<button onclick="darkmode()">dark</button> -
<button onclick="brightmode()">vivid</button>
<script src="/css/script2.js"></script><br>
<i>eyestrain & flash/glitch warning for vivid</i>
</center>
<br>
<center><button class="toggle-gif">toggle gifs (w.i.p)</button></center>
</aside>
<article class="main">
<center><div class="main2">
</div></center>
<br>
<div class="container2">
<div class="box1">
</div>
<div class="box1 child">
</div>
</div>
</article>
<aside class="secondary-div">
</aside>
</div>
</body>
</html>
i only included one css file of the three i use as i figure if one is figured out, the others will have the same/similar solution as the only differences are the files/colors used in the root... though admittedly that didn't seem to work when i tried messing with :active lol. regardless, if needed i can provide the other two css files. i hope i explained myself/what i'm needing clearly, if any clarification is needed i will do my best to elaborate. if you want to see my site, it's
here. (it's also linked on my profile)