mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
Merge pull request #1001 from heygen-com/fix/sub-comp-t0-baseline-regen
test(producer): regenerate sub-comp-t0 baseline + add gsap_from_opacity_noop lint rule
This commit is contained in:
@@ -746,4 +746,99 @@ describe("GSAP rules", () => {
|
|||||||
const finding = result.findings.find((f) => f.code === "gsap_infinite_repeat");
|
const finding = result.findings.find((f) => f.code === "gsap_infinite_repeat");
|
||||||
expect(finding).toBeUndefined();
|
expect(finding).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("errors when CSS opacity:0 + gsap.from({opacity:0}) — invisible forever", () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||||
|
<div id="title" style="opacity: 0; font-size: 120px;">Hello</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.from("#title", { opacity: 0, y: 30, duration: 0.5 }, 0.2);
|
||||||
|
window.__timelines["c1"] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_from_opacity_noop");
|
||||||
|
expect(finding).toBeDefined();
|
||||||
|
expect(finding!.severity).toBe("error");
|
||||||
|
expect(finding!.selector).toBe("#title");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("errors when style block has opacity:0 + gsap.from({opacity:0})", () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||||
|
<div id="hero">Hello</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
#hero { font-size: 200px; color: #fff; opacity: 0; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.from("#hero", { opacity: 0, scale: 3.5, duration: 0.25, ease: "expo.out" }, 0.1);
|
||||||
|
window.__timelines["c1"] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_from_opacity_noop");
|
||||||
|
expect(finding).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does NOT error when gsap.from({opacity:0}) and CSS has no opacity:0", () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||||
|
<div id="title" style="font-size: 120px; color: #fff;">Hello</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.from("#title", { opacity: 0, y: 30, duration: 0.5 }, 0.2);
|
||||||
|
window.__timelines["c1"] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_from_opacity_noop");
|
||||||
|
expect(finding).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does NOT error when gsap.fromTo({opacity:0}, {opacity:1}) — destination overrides CSS", () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||||
|
<div id="title" style="opacity: 0; font-size: 120px;">Hello</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.fromTo("#title", { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.5 }, 0.2);
|
||||||
|
window.__timelines["c1"] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_from_opacity_noop");
|
||||||
|
expect(finding).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does NOT error when gsap.to() uses opacity:0 (exit animation)", () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||||
|
<div id="title" style="opacity: 0;">Hello</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.to("#title", { opacity: 0, duration: 0.5 }, 4.0);
|
||||||
|
window.__timelines["c1"] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_from_opacity_noop");
|
||||||
|
expect(finding).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -843,4 +843,60 @@ export const gsapRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [
|
|||||||
}
|
}
|
||||||
return findings;
|
return findings;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// gsap_from_opacity_noop — CSS opacity:0 + gsap.from({opacity:0}) = invisible forever
|
||||||
|
({ styles, scripts, tags }) => {
|
||||||
|
const findings: HyperframeLintFinding[] = [];
|
||||||
|
const cssOpacityZeroSelectors = new Set<string>();
|
||||||
|
|
||||||
|
for (const style of styles) {
|
||||||
|
for (const [, selector, body] of style.content.matchAll(
|
||||||
|
/([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g,
|
||||||
|
)) {
|
||||||
|
if (body && /opacity\s*:\s*0\s*[;}]/.test(body)) {
|
||||||
|
cssOpacityZeroSelectors.add((selector ?? "").trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const tag of tags) {
|
||||||
|
const inlineStyle = readAttr(tag.raw, "style");
|
||||||
|
if (!inlineStyle || !/opacity\s*:\s*0/.test(inlineStyle)) continue;
|
||||||
|
const id = readAttr(tag.raw, "id");
|
||||||
|
const classes = readAttr(tag.raw, "class")?.split(/\s+/).filter(Boolean) ?? [];
|
||||||
|
if (id) cssOpacityZeroSelectors.add(`#${id}`);
|
||||||
|
for (const cls of classes) cssOpacityZeroSelectors.add(`.${cls}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cssOpacityZeroSelectors.size === 0) return findings;
|
||||||
|
|
||||||
|
for (const script of scripts) {
|
||||||
|
if (!/gsap\.timeline/.test(script.content)) continue;
|
||||||
|
const windows = extractGsapWindows(script.content);
|
||||||
|
|
||||||
|
for (const win of windows) {
|
||||||
|
if (win.method !== "from") continue;
|
||||||
|
if (!win.properties.includes("opacity")) continue;
|
||||||
|
const sel = win.targetSelector;
|
||||||
|
const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
|
||||||
|
if (!cssOpacityZeroSelectors.has(cssKey)) continue;
|
||||||
|
|
||||||
|
findings.push({
|
||||||
|
code: "gsap_from_opacity_noop",
|
||||||
|
severity: "error",
|
||||||
|
message:
|
||||||
|
`"${sel}" has CSS \`opacity: 0\` and a gsap.${win.method}() that also sets opacity to 0. ` +
|
||||||
|
`gsap.from() animates FROM the specified value TO the current CSS value — ` +
|
||||||
|
`since CSS is already 0, the element animates from 0→0 and never becomes visible.`,
|
||||||
|
selector: sel,
|
||||||
|
fixHint:
|
||||||
|
`Remove \`opacity: 0\` from the CSS/inline style on "${sel}". ` +
|
||||||
|
`Let gsap.from({opacity: 0}) handle the initial hidden state — ` +
|
||||||
|
`it will animate FROM 0 TO the CSS value (1 by default).`,
|
||||||
|
snippet: truncateSnippet(win.raw),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findings;
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-display: block;
|
font-display: block;
|
||||||
}</style>
|
}</style><style data-hyperframes-text-rendering="true">html,body,*{text-rendering:geometricPrecision}</style>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=1920, height=1080">
|
<meta name="viewport" content="width=1920, height=1080">
|
||||||
<script>/* inlined: https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js */
|
<script>/* inlined: https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js */
|
||||||
@@ -81,14 +81,14 @@
|
|||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #0f172a;
|
||||||
}
|
}
|
||||||
#root {
|
#root {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #0f172a;
|
||||||
}
|
}
|
||||||
.scene {
|
.scene {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -100,49 +100,66 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-composition-id="hook"] [data-hf-authored-id="hook"] {
|
[data-composition-id="hook"][data-hf-authored-id="hook"] {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #ef4444;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20px;
|
|
||||||
}
|
}
|
||||||
[data-composition-id="hook"] [data-hf-authored-id="hook"] .hook-title {
|
[data-composition-id="hook"][data-hf-authored-id="hook"] .hook-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: #ef4444;
|
||||||
|
}
|
||||||
|
[data-composition-id="hook"][data-hf-authored-id="hook"] .hook-title {
|
||||||
|
position: absolute;
|
||||||
|
top: 250px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Impact, system-ui, sans-serif;
|
font-family: Impact, system-ui, sans-serif;
|
||||||
font-size: 200px;
|
font-size: 280px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #ff3b30;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
[data-composition-id="hook"] [data-hf-authored-id="hook"] .hook-subtitle {
|
[data-composition-id="hook"][data-hf-authored-id="hook"] .hook-subtitle {
|
||||||
|
position: absolute;
|
||||||
|
top: 600px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Arial, system-ui, sans-serif;
|
font-family: Arial, system-ui, sans-serif;
|
||||||
font-size: 60px;
|
font-size: 80px;
|
||||||
color: #f7f3e8;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[data-composition-id="later"] [data-hf-authored-id="later"] {
|
[data-composition-id="later"][data-hf-authored-id="later"] {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0e2c1e;
|
background: #3b82f6;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
[data-composition-id="later"] [data-hf-authored-id="later"] .later-heading {
|
[data-composition-id="later"][data-hf-authored-id="later"] .later-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: #3b82f6;
|
||||||
|
}
|
||||||
|
[data-composition-id="later"][data-hf-authored-id="later"] .later-heading {
|
||||||
|
position: absolute;
|
||||||
|
top: 380px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Arial, system-ui, sans-serif;
|
font-family: Arial, system-ui, sans-serif;
|
||||||
font-size: 120px;
|
font-size: 160px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #f7f3e8;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}</style>
|
}</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -150,6 +167,7 @@
|
|||||||
<div id="root" data-composition-id="main" data-start="0" data-duration="6" data-width="1920" data-height="1080">
|
<div id="root" data-composition-id="main" data-start="0" data-duration="6" data-width="1920" data-height="1080">
|
||||||
<!-- First sub-comp at near-zero start: the bug trigger -->
|
<!-- First sub-comp at near-zero start: the bug trigger -->
|
||||||
<div style="width:1920px;height:1080px" data-composition-file="compositions/hook.html" data-hf-authored-id="hook" data-height="1080" data-width="1920" id="scene-hook" class="scene" data-layout-allow-overflow="" data-composition-id="hook" data-start="0.001" data-duration="2.0" data-track-index="0">
|
<div style="width:1920px;height:1080px" data-composition-file="compositions/hook.html" data-hf-authored-id="hook" data-height="1080" data-width="1920" id="scene-hook" class="scene" data-layout-allow-overflow="" data-composition-id="hook" data-start="0.001" data-duration="2.0" data-track-index="0">
|
||||||
|
<div class="hook-bg"></div>
|
||||||
<div class="hook-title">BREAKING</div>
|
<div class="hook-title">BREAKING</div>
|
||||||
<div class="hook-subtitle">Transfer confirmed</div>
|
<div class="hook-subtitle">Transfer confirmed</div>
|
||||||
|
|
||||||
@@ -161,6 +179,7 @@
|
|||||||
|
|
||||||
<!-- Second sub-comp at a later start: works correctly -->
|
<!-- Second sub-comp at a later start: works correctly -->
|
||||||
<div style="width:1920px;height:1080px" data-composition-file="compositions/later.html" data-hf-authored-id="later" data-height="1080" data-width="1920" id="scene-later" class="scene" data-layout-allow-overflow="" data-composition-id="later" data-start="2.5" data-duration="3.5" data-track-index="1">
|
<div style="width:1920px;height:1080px" data-composition-file="compositions/later.html" data-hf-authored-id="later" data-height="1080" data-width="1920" id="scene-later" class="scene" data-layout-allow-overflow="" data-composition-id="later" data-start="2.5" data-duration="3.5" data-track-index="1">
|
||||||
|
<div class="later-bg"></div>
|
||||||
<div class="later-heading">Second Scene</div>
|
<div class="later-heading">Second Scene</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -462,7 +481,6 @@
|
|||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
var scope = "#hook";
|
var scope = "#hook";
|
||||||
|
|
||||||
// Title slams in at 0.1s
|
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
scope + " .hook-title",
|
scope + " .hook-title",
|
||||||
{ scale: 3.5, opacity: 0 },
|
{ scale: 3.5, opacity: 0 },
|
||||||
@@ -470,7 +488,6 @@
|
|||||||
0.1,
|
0.1,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Subtitle fades in at 0.5s
|
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
scope + " .hook-subtitle",
|
scope + " .hook-subtitle",
|
||||||
{ y: 30, opacity: 0 },
|
{ y: 30, opacity: 0 },
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:3ac5c0ef3b7e6e31a49d361a62ba2ca8ac1532544eca9f6f60e0ede52836693c
|
oid sha256:7acd4e38f70f528105dabd4eb9717e2ab369755817e42141c98401ae5ed6009c
|
||||||
size 20587
|
size 426899
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template id="hook-template">
|
<template id="hook-template">
|
||||||
<div id="hook" data-composition-id="hook" data-width="1920" data-height="1080">
|
<div id="hook" data-composition-id="hook" data-width="1920" data-height="1080">
|
||||||
|
<div class="hook-bg"></div>
|
||||||
<div class="hook-title">BREAKING</div>
|
<div class="hook-title">BREAKING</div>
|
||||||
<div class="hook-subtitle">Transfer confirmed</div>
|
<div class="hook-subtitle">Transfer confirmed</div>
|
||||||
|
|
||||||
@@ -9,24 +10,34 @@
|
|||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #ef4444;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
#hook .hook-bg {
|
||||||
justify-content: center;
|
position: absolute;
|
||||||
flex-direction: column;
|
inset: 0;
|
||||||
gap: 20px;
|
background: #ef4444;
|
||||||
}
|
}
|
||||||
#hook .hook-title {
|
#hook .hook-title {
|
||||||
|
position: absolute;
|
||||||
|
top: 250px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Impact, system-ui, sans-serif;
|
font-family: Impact, system-ui, sans-serif;
|
||||||
font-size: 200px;
|
font-size: 280px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #ff3b30;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
#hook .hook-subtitle {
|
#hook .hook-subtitle {
|
||||||
|
position: absolute;
|
||||||
|
top: 600px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Arial, system-ui, sans-serif;
|
font-family: Arial, system-ui, sans-serif;
|
||||||
font-size: 60px;
|
font-size: 80px;
|
||||||
color: #f7f3e8;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -38,7 +49,6 @@
|
|||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
var scope = "#hook";
|
var scope = "#hook";
|
||||||
|
|
||||||
// Title slams in at 0.1s
|
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
scope + " .hook-title",
|
scope + " .hook-title",
|
||||||
{ scale: 3.5, opacity: 0 },
|
{ scale: 3.5, opacity: 0 },
|
||||||
@@ -46,7 +56,6 @@
|
|||||||
0.1,
|
0.1,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Subtitle fades in at 0.5s
|
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
scope + " .hook-subtitle",
|
scope + " .hook-subtitle",
|
||||||
{ y: 30, opacity: 0 },
|
{ y: 30, opacity: 0 },
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template id="later-template">
|
<template id="later-template">
|
||||||
<div id="later" data-composition-id="later" data-width="1920" data-height="1080">
|
<div id="later" data-composition-id="later" data-width="1920" data-height="1080">
|
||||||
|
<div class="later-bg"></div>
|
||||||
<div class="later-heading">Second Scene</div>
|
<div class="later-heading">Second Scene</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -8,16 +9,23 @@
|
|||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0e2c1e;
|
background: #3b82f6;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
#later .later-bg {
|
||||||
justify-content: center;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: #3b82f6;
|
||||||
}
|
}
|
||||||
#later .later-heading {
|
#later .later-heading {
|
||||||
|
position: absolute;
|
||||||
|
top: 380px;
|
||||||
|
left: 0;
|
||||||
|
width: 1920px;
|
||||||
|
text-align: center;
|
||||||
font-family: Arial, system-ui, sans-serif;
|
font-family: Arial, system-ui, sans-serif;
|
||||||
font-size: 120px;
|
font-size: 160px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #f7f3e8;
|
color: #ffffff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #0f172a;
|
||||||
}
|
}
|
||||||
#root {
|
#root {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #07110d;
|
background: #0f172a;
|
||||||
}
|
}
|
||||||
.scene {
|
.scene {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
Reference in New Issue
Block a user