<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Data Viz Projects]]></title><description><![CDATA[Data Viz Projects]]></description><link>https://data-viz-projects.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 06 Sep 2026 19:15:38 GMT</lastBuildDate><atom:link href="https://data-viz-projects.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Halloween Dashboard with Spotlight Effect, CSS Masks, and Flexmonster]]></title><description><![CDATA[Even though Halloween passed a few days ago, its spirit is still in the air, and I'm always up for a new challenge. As a developer who works with tables, reports, and dev libraries, I decided to add some eerie vibe to data visualization.
So, in this ...]]></description><link>https://data-viz-projects.hashnode.dev/building-a-halloween-dashboard-with-spotlight-effect-css-masks-and-flexmonster</link><guid isPermaLink="true">https://data-viz-projects.hashnode.dev/building-a-halloween-dashboard-with-spotlight-effect-css-masks-and-flexmonster</guid><category><![CDATA[data visualization]]></category><category><![CDATA[flexmonster]]></category><category><![CDATA[CSS]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Javascript library]]></category><category><![CDATA[web dev]]></category><dc:creator><![CDATA[Daria Filozop]]></dc:creator><pubDate>Mon, 10 Nov 2025 13:27:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762734256966/1f0f383a-2332-4641-b613-2bf84c850978.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Even though Halloween passed a few days ago, its spirit is still in the air, and I'm always up for a new challenge. As a developer who works with tables, reports, and dev libraries, I decided to add some eerie vibe to data visualization.</p>
<p>So, in this quick tutorial, I’ll show how spooky CSS masks can add a whole new vibe to your reports.</p>
<p>The idea sparked from the previous week’s CodePen Challenge: <a target="_blank" href="https://codepen.io/challenges/2025/october/2">“Halloween Masks.”</a> Say no more… challenge accepted!</p>
<p>For the dataset, I’ve chosen <a target="_blank" href="https://www.kaggle.com/datasets/GoogleNewsLab/frightgeist-2017-costumes-by-state">“Frightgeist 2017: Costumes by State”</a>, which displays the most popular Halloween costumes in each state in 2017. So, now the dataset even has a 'masks' topic.</p>
<p>As a tech stack, I will use Flexmonster Pivot. This modern web library enables interactive reports and creative visualization of insights (which is precisely what I need for this project).</p>
<p><strong>Step 1: Preprocessing the Dataset</strong></p>
<p>At first, I wanted to make the dataset more catchy, so I added to each type of costume emoji, and it instantly gave the data a playful, seasonal touch:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762509944549/2a01f182-bb11-4a9d-b8df-c76fa452dcb2.png" alt class="image--center mx-auto" /></p>
<p>As the next part of this step, I created the <em>getData()</em> function, where I defined specific types for each field. So, we’ll see Halloween costumes for every state and how they rank in popularity:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> [
        {
            <span class="hljs-attr">State</span>: {
                <span class="hljs-attr">caption</span>: <span class="hljs-string">"State"</span>,
                <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span>
            },
            <span class="hljs-string">"#1"</span>: {
                <span class="hljs-attr">caption</span>: <span class="hljs-string">"#1"</span>,
                <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span>
            },
            <span class="hljs-string">"#2"</span>: {
                <span class="hljs-attr">caption</span>: <span class="hljs-string">"#2"</span>,
                <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span>
            },
    …
        },
        [
            <span class="hljs-string">"Alaska"</span>,
            <span class="hljs-string">"Ninja 🥷"</span>,
            <span class="hljs-string">"Monster 👹"</span>,
            <span class="hljs-string">"Wonder Woman 🦸‍♀️"</span>,
            <span class="hljs-string">"Clown 🤡"</span>,
            <span class="hljs-string">"Rabbit 🐰"</span>
        ],
</code></pre>
<p><strong>Step 2: Setting Up the Project</strong></p>
<p>Here I use Flexmonster to visualize all the raw data and then group it, so we can easily explore it and get valuable insights.</p>
<p>So, I created an HTML file and added Flexmonster to the <em>&lt;head&gt;</em> section:</p>
<pre><code class="lang-javascript">&lt;link rel=<span class="hljs-string">"stylesheet"</span> type=<span class="hljs-string">"text/css"</span> href=<span class="hljs-string">"https://cdn.flexmonster.com/theme/dark/flexmonster.min.css"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.flexmonster.com/flexmonster.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>After it, I added a title and a container for the pivot table inside the <em>&lt;body&gt;</em> section:</p>
<pre><code class="lang-javascript">&lt;h1&gt;Halloween costumes by state 👻&lt;/h1&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pivot-container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p><strong>Step 3: Setting Up the Pivot Table</strong></p>
<p>So now it’s time for Flexmonster configurations! To render our whole dataset, all you need to do is create Flexmonster instance, set the needed configs, and mention the needed rows and columns in the slice:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> Flexmonster({
        <span class="hljs-attr">container</span>: <span class="hljs-string">"#pivot-container"</span>,
        <span class="hljs-attr">componentFolder</span>: <span class="hljs-string">"https://cdn.flexmonster.com/"</span>,
        <span class="hljs-attr">width</span>: <span class="hljs-string">"100%"</span>,
        <span class="hljs-attr">height</span>: <span class="hljs-number">600</span>,
        <span class="hljs-attr">report</span>: {
            <span class="hljs-attr">dataSource</span>: {
                <span class="hljs-attr">data</span>: getData()
            },
            <span class="hljs-attr">slice</span>: {
                <span class="hljs-attr">rows</span>: [
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"State"</span> }
                ],
                <span class="hljs-attr">columns</span>: [
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"#1"</span> },
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"#2"</span> },
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"#3"</span> },
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"#4"</span> },
                    { <span class="hljs-attr">uniqueName</span>: <span class="hljs-string">"#5"</span> }
                ]
            },
            <span class="hljs-attr">options</span>: {
                <span class="hljs-attr">grid</span>: {
                    <span class="hljs-attr">showTotals</span>: <span class="hljs-string">"off"</span>
                },
                <span class="hljs-attr">chart</span>: {
                    <span class="hljs-attr">type</span>: <span class="hljs-string">"bar"</span>
                }
            }
        }
    });
</code></pre>
<p><strong>Step 4: Styling</strong></p>
<p>Now it’s time for real magic! In this step, we will apply a CSS mask and spotlight effect, which adds an authentic Halloween atmosphere to our demo. However, before that, I performed some basic styling, such as setting a dark background, using a new font, and cell coloring, among other tasks.</p>
<pre><code class="lang-javascript">@<span class="hljs-keyword">import</span> url(<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Original+Surfer&amp;display=swap"</span>);

body {
    <span class="hljs-attr">height</span>: <span class="hljs-number">100</span>vh;
    margin: <span class="hljs-number">0</span>;
    display: grid;
    place-items: center;
    background: #<span class="hljs-number">100</span>d08;
}

h1,
#pivot-container [<span class="hljs-class"><span class="hljs-keyword">class</span>^</span>=<span class="hljs-string">"fm"</span>] {
    font-family: <span class="hljs-string">"Original Surfer"</span>, sans-serif !important;
}

h1 {
    <span class="hljs-attr">color</span>: #fff;
}

#fm-pivot-view .fm-grid-view .fm-data-sheet div.fm-cell.green {
    background-color: #c4d6b0 !important;
    color: #<span class="hljs-number">000</span> !important;
}

#fm-pivot-view .fm-grid-view div.fm-cell.orange {
    background-color: #ffc15e !important;
    color: #<span class="hljs-number">000</span> !important;
}
</code></pre>
<p>But to make different colors for cells depending on row index, I needed to complete my JavaScript code a bit by adding <em>customizeCellFunction()</em>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">customizeCellFunction</span>(<span class="hljs-params">cell, data</span>) </span>{
    <span class="hljs-keyword">if</span> (data.type == <span class="hljs-string">"value"</span>) {
        <span class="hljs-keyword">if</span> (data.rowIndex % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) {
            cell.addClass(<span class="hljs-string">"orange"</span>);
        } <span class="hljs-keyword">else</span> {
            cell.addClass(<span class="hljs-string">"green"</span>);
        }
    }
}
</code></pre>
<p><strong>Step 4.1: CSS-Masks effect</strong></p>
<p>Since this CodePen Challenge is about masks, I decided to create a mask effect with a radial gradient for the pivot container. It can be easily done by adding this code snippet:</p>
<pre><code class="lang-javascript">.fm-ui-container#fm-pivot-view {
    -webkit-mask-image: radial-gradient(circle, white <span class="hljs-number">70</span>%, transparent <span class="hljs-number">100</span>%);
    mask-image: radial-gradient(circle, white <span class="hljs-number">70</span>%, transparent <span class="hljs-number">100</span>%);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762508465514/712d9118-d9e4-496b-ac61-b898f1b0680d.png" alt class="image--center mx-auto" /></p>
<p><strong>Step 4.2: Spotlight</strong></p>
<p>Let’s add some drama to our pivot grid! The spotlight effect creates a stage-like feel, highlighting one area while cloaking the rest in shadow. Perfect for Halloween, and easy to build with CSS.</p>
<p>This effect darkens the entire screen except for a circular area that follows the mouse, and all you need to do to achieve it is make minor adjustments in the CSS part:</p>
<pre><code class="lang-javascript">.spotlight {
    z-index: <span class="hljs-number">1</span>;
    position: fixed;
    inset: <span class="hljs-number">0</span>;
    background-image: radial-gradient(
        circle at <span class="hljs-keyword">var</span>(--clientX, <span class="hljs-number">50</span>%) <span class="hljs-keyword">var</span>(--clientY, <span class="hljs-number">50</span>%),
        transparent <span class="hljs-number">6</span>em,
        black <span class="hljs-number">8</span>em
    );
}

.spotlight.off {
    <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span>;
    z-index: <span class="hljs-number">0</span>;
}
</code></pre>
<p>Next, I wanted users to control the effect. A quick toggle button does the trick:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> spotlight = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".spotlight"</span>);
<span class="hljs-keyword">const</span> toggleBtn = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#toggle-spotlight"</span>);
<span class="hljs-keyword">let</span> spotlightEnabled = <span class="hljs-literal">false</span>;

toggleBtn.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
    spotlightEnabled = !spotlightEnabled;
    spotlight.classList.toggle(<span class="hljs-string">"off"</span>, !spotlightEnabled);
    toggleBtn.textContent = spotlightEnabled
        ? <span class="hljs-string">"💡 Turn off spotlight"</span>
        : <span class="hljs-string">"🌑 Turn on spotlight"</span>;
});

<span class="hljs-built_in">document</span>.body.addEventListener(<span class="hljs-string">"mousemove"</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-built_in">document</span>.body.style.setProperty(<span class="hljs-string">"--clientX"</span>, e.clientX + <span class="hljs-string">"px"</span>);
    <span class="hljs-built_in">document</span>.body.style.setProperty(<span class="hljs-string">"--clientY"</span>, e.clientY + <span class="hljs-string">"px"</span>);
});
</code></pre>
<p>Finally, added some CSS styling for the button:</p>
<pre><code class="lang-javascript">#toggle-spotlight {
    <span class="hljs-attr">position</span>: absolute;
    top: <span class="hljs-number">1</span>rem;
    right: <span class="hljs-number">1</span>rem;
    background: #ff7518;
    color: #<span class="hljs-number">000</span>;
    font-family: <span class="hljs-string">"Original Surfer"</span>, sans-serif;
    font-size: <span class="hljs-number">1</span>rem;
    border: none;
    border-radius: <span class="hljs-number">8</span>px;
    padding: <span class="hljs-number">8</span>px <span class="hljs-number">14</span>px;
    cursor: pointer;
    box-shadow: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">10</span>px #ff7518aa;
    z-index: <span class="hljs-number">400</span>;
}

#toggle-spotlight:hover {
    <span class="hljs-attr">background</span>: #ffa34a;
}
</code></pre>
<p>And don’t forget about <em>&lt;button&gt;</em> in HTML file:</p>
<pre><code class="lang-javascript">&lt;button id=<span class="hljs-string">"toggle-spotlight"</span>&gt;💡 Toggle spotlight&lt;/button&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762509087703/35e4e3e8-3056-4ca9-a5e1-5104088a0c14.gif" alt class="image--center mx-auto" /></p>
<p>Actually, I came up with this idea by reading an article on FrontendMasters. If you want to explore even more advanced spotlight effects, I highly recommend reading the “<a target="_blank" href="https://frontendmasters.com/blog/css-spotlight-effect/">CSS Spotlight Effect</a>” article.</p>
<p>That's all there is to it! We’ve successfully blended data visualization with a bit of CSS magic.</p>
<p>You can explore the final, fully functional demo and all its code here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/flexmonster/pen/raxdMeX">https://codepen.io/flexmonster/pen/raxdMeX</a></div>
<p> </p>
<p>And since we were looking at the data: are you still curious about the most popular Halloween costume across different states? In 2017 it was Wonder Woman, taking first place in a whopping 24 states!</p>
<p>Moreover, in Delaware, the first place went to the “IT” costume. Interestingly, it’s hard to tell, does it refer to Pennywise from Stephen King’s novel or to a programmer?</p>
<p>I’d be happy to hear your thoughts on this demo, any ideas for improvements, or suggestions for further articles.</p>
]]></content:encoded></item></channel></rss>