<?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[Rajat Kapoor's dev blog]]></title><description><![CDATA[Rajat Kapoor's dev blog]]></description><link>https://blog.rajatkapoor.me</link><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 10:53:58 GMT</lastBuildDate><atom:link href="https://blog.rajatkapoor.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[CSS Container Queries - The future of responsive web design is almost here]]></title><description><![CDATA[With the huge number of smartphone users and increasing power of these devices, ensuring that your web applications run fine on all screen sizes is more important than ever. Fortunately CSS provides a couple of ways to style the same HTML in differen...]]></description><link>https://blog.rajatkapoor.me/css-container-queries-the-future-of-responsive-web-design-is-almost-here</link><guid isPermaLink="true">https://blog.rajatkapoor.me/css-container-queries-the-future-of-responsive-web-design-is-almost-here</guid><category><![CDATA[CSS]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Responsive Web Design]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rajat Kapoor]]></dc:creator><pubDate>Tue, 25 May 2021 16:14:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621959249860/4dsC2OoMH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the huge number of smartphone users and increasing power of these devices, ensuring that your web applications run fine on all screen sizes is more important than ever. Fortunately CSS provides a couple of ways to style the same HTML in different ways on different devices.</p>
<h2 id="responsive-web-design-right-now">Responsive web design right now</h2>
<blockquote>
<p>You can skip to the next section if you're already familiar with <code>@media</code> queries.</p>
</blockquote>
<p>We can use <code>@media</code> queries in our CSS to conditionally apply CSS styles on the basis of the device or browser/user-agent properties. These properties could be the width of the screen, orientation of the device, whether the device is a screen reader or a printer, etc. </p>
<p>Here is a small demo showing how media queries work.</p>
<p>We will just add one <code>div</code> in our html.</p>
<pre><code>&lt;div <span class="hljs-keyword">class</span>="box"&gt;
    This <span class="hljs-keyword">is</span> a responsive <span class="hljs-type">box</span>. Resize your browser width <span class="hljs-keyword">to</span> see the styles change
&lt;div&gt;
</code></pre><p>And here is our CSS:</p>
<pre><code><span class="hljs-selector-class">.box</span> {
  <span class="hljs-attribute">background</span>: lightblue;
  <span class="hljs-attribute">width</span>:<span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>:<span class="hljs-number">100vh</span>;
}

<span class="hljs-keyword">@media</span>(max-width:<span class="hljs-number">800px</span>) {
  <span class="hljs-selector-class">.box</span> {
    <span class="hljs-attribute">background</span>: hotpink;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  }
}
</code></pre><p>You can check the whole demo here:
https://codepen.io/rajatkapoor/full/NWpgWor</p>
<p>If you open the above link on a desktop/laptop you will see a screen with a blue background with black colored text written on it. Something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621947588544/Q_HP3Wciv.png" alt="screely-1621947531671.png" /></p>
<p>But if you open this on a smartphone, you will have a pink background instead of blue and the text would be written in white.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621947616886/tdrRstGOW.png" alt="screely-1621947570197.png" /></p>
<h4 id="magic-right">Magic right?</h4>
<p>This is possible because of the <code>@media</code> queries. This happens because we apply certain styles only when the width of our device screen is less than <code>800px</code>. This is the CSS that causes the different styles on mobile and desktop.</p>
<pre><code><span class="hljs-keyword">@media</span>(max-width:<span class="hljs-number">800px</span>) {
  <span class="hljs-selector-class">.box</span> {
    <span class="hljs-attribute">background</span>: hotpink;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  }
}
</code></pre><h1 id="enter-container-queries">Enter <code>@container</code> queries</h1>
<blockquote>
<p>@container queries are only supported on Chrome Canary with the <code>enable-container-queries</code> flag enabled. You can download Chrome Canary  <a target="_blank" href="https://www.google.com/intl/en_in/chrome/canary/">here</a>. Once installed, open the URL chrome://flags/#enable-container-queries and enable container queries.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621937509149/4B5WzT8fK.png" alt="Screenshot 2021-05-25 at 3.41.42 PM.png" /></p>
<p>There is a polyfill under development that you can use to use container queries today. You can check it out <a target="_blank" href="https://www.bram.us/2021/04/27/a-first-look-at-cqfill-a-polyfill-for-css-container-queries/">here.</a></p>
</blockquote>
<p><code>@container</code> queries are one of the many features that are coming to CSS. Unlike media queries, which can only let you conditionally apply CSS styles on the basis of the browser properties(width, orientation, etc), container queries allow you to conditionally apply styles based on the properties of the container!</p>
<p>For example, using container queries you can style cards to appear differently depending on the size of the element they are placed in. And that is what we will try to build.</p>
<h2 id="heres-what-what-we-will-build">Here's what what we will build</h2>
<p>We will build a card that will change styles depending on the width of its container, and not the width of the screen.</p>
<p><a target="_blank" href="https://container-queries.vercel.app/">Here's a demo that works only on Chrome canary.</a></p>
<p><a target="_blank" href="https://container-queries-polyfill.vercel.app/">Here's the same demo with the <code>cqfill</code> polyfill.</a> </p>
<p>You can see the full code of this demo in this <a target="_blank" href="https://github.com/rajatkapoor/container-queries">github repository</a>.</p>
<h2 id="lets-try-it-out">Let's try it out</h2>
<p>We'll use good old plain HTML and CSS for this project. Here is our initial HTML. Notice that we have also linked to our own "styles.css file". </p>
<pre><code><span class="hljs-comment">&lt;!-- index.html --&gt;</span>
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Container Queries | Rajat Kapoor<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- our own styles --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"./styles.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>We will start by creating a very simple card, with an image, title, and some text. This card will have a <code>card--header</code> with an image and a <code>card--body</code> with a title and other card content. The card is styled using <code>flex</code> with <code>flex-direction: row</code>, so the image stays on the left-hand side and the rest of the text content on the right.</p>
<p>We will wrap this card in a <code>div</code> with class <code>parent large</code> and will wrap all of this in a <code>container</code> to center everything on the page.</p>
<pre><code><span class="hljs-comment">&lt;!-- index.html  --&gt;</span>
<span class="hljs-comment">&lt;!-- ... --&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parent large"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card "</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card--header "</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card--image"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./img.jpeg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"card image"</span>&gt;</span>
                    <span class="hljs-comment">&lt;!-- we have this img.jpeg file in our folder --&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card--body "</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card--title "</span>&gt;</span>
                        Lorem ipsum dolor sit amet.
                    <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card--content "</span>&gt;</span>
                        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nihil expedita accusantium, quidem
                        ducimus doloribus architecto a est deleniti, rerum saepe hic. Repellendus itaque ab officiis
                        voluptate ea earum perferendis consequatur!
                    <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre><pre><code><span class="hljs-comment">/* styles.css */</span>
<span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">background-color</span>: lightblue;
}

<span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">place-items</span>: center;
    <span class="hljs-attribute">grid-gap</span>: <span class="hljs-number">1em</span>;
}

<span class="hljs-selector-class">.card</span> {
    <span class="hljs-attribute">background</span>: white;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2em</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: row;
    <span class="hljs-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2em</span>;
}

<span class="hljs-selector-class">.card--header</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.card--image</span> {
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1em</span>;
    <span class="hljs-attribute">object-fit</span>: cover;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.card--body</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2em</span>;
    <span class="hljs-attribute">flex</span>: <span class="hljs-number">3</span>
}

<span class="hljs-selector-class">.card--header</span> {
    <span class="hljs-attribute">flex</span>: <span class="hljs-number">2</span>
}

<span class="hljs-selector-class">.large</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}
</code></pre><p>This is how your page will look:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621947469220/_qfD7xtpG.png" alt="screely-1621947454927.png" />
We will now add another <code>div</code> with class <code>parent small</code> and copy-paste the same card into it. We will also define styles for the <code>small</code> class.</p>
<pre><code><span class="hljs-comment">&lt;!-- index.html --&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parent large"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
               <span class="hljs-comment">&lt;!-- ...card --&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parent small"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
               <span class="hljs-comment">&lt;!-- ...card --&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre><pre><code><span class="hljs-comment">// styles.css</span>

<span class="hljs-selector-class">.small</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">500px</span>;
}
</code></pre><p>Note that both the cards are exactly the same and are just lying in two different <code>div</code>s. And this is how they look:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621947760881/1YEI-jGLG.png" alt="screely-1621947739345.png" /></p>
<h2 id="adding-container-queries">Adding container queries</h2>
<p>We want the card to have the text content below the image in case the width of the container is less than 500px.  We will also change the background of our card to hotpink and make the text white to make the changes more noticable.
For container queries to work, we need to add CSS to the container to define the "containment context" — the container queries of the children inside this containment context react to the properties of this container. We will make the <code>div</code>s with class <code>parent</code> as the containment context of these cards. To do that, we will modify the CSS of the <code>parent</code> class.</p>
<pre><code><span class="hljs-comment">/* styles.css */</span>

<span class="hljs-selector-class">.parent</span> {
    <span class="hljs-attribute">contain</span>: layout inline-size style;
}
</code></pre><p>Now we can add container queries to our card.</p>
<pre><code><span class="hljs-comment">/* styles.css */</span>

<span class="hljs-variable">@container</span>(<span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>) {
    <span class="hljs-selector-class">.card</span> {
        <span class="hljs-attribute">flex-direction</span>: column;
        <span class="hljs-attribute">background-color</span>: pink;
    }
}
</code></pre><p>Thats it! Now if you go back to your browser, you will see that the card in the <code>div</code> with the class <code>small</code> has the new styles applied. </p>
<h3 id="yay">Yay 🎉</h3>
<p>We were able to control the styling on the basis of the container size and not just the device properties (screen size). That is the power of container queries.</p>
<h1 id="bonus-lets-make-the-parent-resizable">Bonus — Let's make the <code>parent</code> resizable</h1>
<p>Do you know you can quickly make anything resizable by just adding CSS. We'll do it to our <code>parent</code>class.</p>
<pre><code><span class="hljs-comment">/* styles.css */</span>

<span class="hljs-selector-class">.parent</span> {
    <span class="hljs-attribute">contain</span>: layout inline-size style;
    <span class="hljs-attribute">resize</span>: horizontal;
    <span class="hljs-attribute">overflow</span>: auto;
}
</code></pre><p>Now both the <code>parent</code> <code>div</code>s can be resized horizontally to see our container queries working in action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621950303218/RIJaqv3ZG-.gif" alt="CPT2105251904-1675x864-min.gif" /></p>
<h1 id="conclusion">Conclusion</h1>
<p>With <code>container</code> queries, we will be able to approach responsive designs in a much smarter way. That said, <code>container</code> queries are in early stages of development. It is not recommended to use these in production right now. In fact, CSSWG changed the syntax between the time I started to write this article to the time I finished writing it 😅.</p>
<p><a target="_blank" href="https://twitter.com/therajatkapoor">Follow me on twitter</a> to get more web development related content.</p>
<blockquote>
<p>Special thanks to <a target="_blank" href="https://twitter.com/shadeed9">Ahmad Shadeed</a> for helping me with debugging why my <code>container</code> queries were not working in Chrome Canary. You can also read more about container queries in <a target="_blank" href="https://ishadeed.com/article/say-hello-to-css-container-queries/">this article</a> </p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Create your dev portfolio - Part 1: First things first]]></title><description><![CDATA[In this post we will set up the foundations for our portfolio:

Create a Next JS app
Set up Chakra UI with a theme
Set up automatic deploys on Vercel using Github

So let's get started.
Intro
I have been developing web applications since my college d...]]></description><link>https://blog.rajatkapoor.me/create-your-dev-portfolio-part-1-first-things-first</link><guid isPermaLink="true">https://blog.rajatkapoor.me/create-your-dev-portfolio-part-1-first-things-first</guid><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[portfolio]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rajat Kapoor]]></dc:creator><pubDate>Mon, 17 May 2021 15:11:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620918116803/qU9stb6fT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post we will set up the foundations for our portfolio:</p>
<ul>
<li>Create a Next JS app</li>
<li>Set up Chakra UI with a theme</li>
<li>Set up automatic deploys on Vercel using Github</li>
</ul>
<p>So let's get started.</p>
<h1 id="intro">Intro</h1>
<p>I have been developing web applications since my college days and been coding professionally for over 6 years. I have owned the domain  <a target="_blank" href="rajatkapoor.me">https://rajatkapoor.me</a> for so long but have never hosted anything on it. Now is the time.</p>
<p>In this series of posts, I will create a decent-looking developer portfolio for myself using  <a target="_blank" href="https://nextjs.org/">NextJs</a>  and  <a target="_blank" href="https://chakra-ui.com/">Chakra UI</a>. I will then host it up on  <a target="_blank" href="https://vercel.com/">Vercel</a> and point my domain (https://rajatkapoor.me) to it.</p>
<p>You can also follow along and create a developer portfolio of your own. You can follow on my progress <a target="_blank" href="https://rajatkapoor.vercel.app/">here</a>  and check the  <a target="_blank" href="https://github.com/rajatkapoor/next.rajatkapoor.me">github repository here</a>.</p>
<h3 id="disclaimer">Disclaimer:</h3>
<p>I am horrible at design, so I will be looking at design resources and other dev portfolios to get inspiration.</p>
<h2 id="create-a-next-js-app">Create a next JS App</h2>
<p>We'll start with creating a new Next js app and run it</p>
<pre><code><span class="hljs-selector-tag">npx</span> <span class="hljs-selector-tag">create-next-app</span> <span class="hljs-selector-tag">portfolio</span> <span class="hljs-comment">// "portfolio" is the name of the app, you could call it anything you like</span>

<span class="hljs-selector-tag">cd</span> <span class="hljs-selector-tag">portfolio</span>

<span class="hljs-comment">// to run the app</span>
<span class="hljs-selector-tag">yarn</span> <span class="hljs-selector-tag">dev</span>
</code></pre><p>You will see an output like this on your screen</p>
<pre><code><span class="hljs-string">ready</span> <span class="hljs-bullet">-</span> <span class="hljs-string">started</span> <span class="hljs-string">server</span> <span class="hljs-string">on</span> <span class="hljs-number">0.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">:3000,</span> <span class="hljs-attr">url:</span> <span class="hljs-string">http://localhost:3000</span>
</code></pre><p>Go to the URL that's shown in your terminal and you will be able to see your app in action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620909634991/mq57sEAL4.png" alt="Screenshot 2021-05-13 at 6.10.27 PM.png" /></p>
<h2 id="setup-chakra-ui">Setup Chakra-UI</h2>
<p><a target="_blank" href="https://chakra-ui.com/">Chakra UI</a>  is a react component library with a great set of components and a prop based model of styling them. All components in Chakra UI are accessible and can be configured with a very well defined theming system. With Chakra UI, you can quickly build accessible React apps. To install it in your app:</p>
<pre><code><span class="hljs-comment">// make sure you're inside the portfolio folder</span>

yarn add <span class="hljs-meta">@chakra</span>-ui/react <span class="hljs-meta">@emotion</span>/<span class="hljs-symbol">react@</span>^<span class="hljs-number">11</span> <span class="hljs-meta">@emotion</span>/<span class="hljs-symbol">styled@</span>^<span class="hljs-number">11</span> framer-<span class="hljs-symbol">motion@</span>^<span class="hljs-number">4</span>
</code></pre><p>Chakra UI apps have to be wrapped in a <code>&lt;ChakraProvider&gt;</code> for them to function correctly. We will wrap our react app's root component inside it. NextJS expects this root component to be default exported from a special file - <code>pages/_app.js</code></p>
<pre><code><span class="hljs-comment">// pages/_app.js</span>

<span class="hljs-keyword">import</span> { ChakraProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span></span>
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp
</code></pre><h3 id="adding-a-theme">Adding a theme</h3>
<p>Chakra UI has a robust theme system, that allows you to re-use styles and add styling rules in a single place. We will neither add any relevant theme-related changes, nor utilize the full power of this theme. But we will configure it and keep it ready for use when the time comes.</p>
<p>For this, create a <code>theme.js</code> file at the root directory of your app.</p>
<pre><code><span class="hljs-comment">// ./theme.js</span>

<span class="hljs-keyword">import</span> { extendTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

<span class="hljs-keyword">const</span> colors = {
  <span class="hljs-attr">brand</span>: {
    <span class="hljs-number">900</span>: <span class="hljs-string">"#1a365d"</span>,
    <span class="hljs-number">800</span>: <span class="hljs-string">"#153e75"</span>,
    <span class="hljs-number">700</span>: <span class="hljs-string">"#2a69ac"</span>,
  },
};

<span class="hljs-keyword">const</span> theme = extendTheme({ colors });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> theme;
</code></pre><p>and then pass this <code>theme</code> to the <code>&lt;ChakraProvider&gt;</code> in <code>pages/_app.js</code>.</p>
<pre><code><span class="hljs-comment">// pages/_app.js</span>

<span class="hljs-keyword">import</span> { ChakraProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

<span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">"../theme"</span>; <span class="hljs-comment">// &lt;- import here</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span> <span class="hljs-attr">theme</span>=<span class="hljs-string">{theme}</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp;
</code></pre><p>Now that we are all set up, let's update our 'pages/index.js' file to use some of the components from Chakra UI.</p>
<pre><code><span class="hljs-comment">// ./pages/index.js</span>

<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">"next/image"</span>;
<span class="hljs-keyword">import</span> { Box } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">w</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">100</span>%"}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Rajat Kapoor - Full stack developer<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span>
          <span class="hljs-attr">content</span>=<span class="hljs-string">"Rajat Kapoor is a full stack developer from India"</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.ico"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Box</span>&gt;</span>hi<span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span></span>
  );
}
</code></pre><p>You will see a small but rewarding message on the top left 😎
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620911644615/i4nuHRRji.png" alt="Screenshot 2021-05-13 at 6.43.57 PM.png" /></p>
<h2 id="hosting-on-vercel">Hosting on vercel</h2>
<p><em>This section assumes you know basics of git and have set up this repository on Github or a similar platform. If that is not the case, please look out for already existing resources from which you can learn those things. If you're still not able to set it up, drop a message in the comments and I will be happy to help you out.</em></p>
<p><a target="_blank" href="https://vercel.com/">Vercel</a> is a web hosting platform that allows you to host your NextJS (and many more types of apps) for free. It is made by the same people who made NextJS and provides a simple but powerful developer experience, especially for NextJS apps. Now let's get this hosted on Vercel, so that we can share the progress of our portfolio with everyone and get early feedback.</p>
<p>Head on to <a target="_blank" href="https://vercel.com/">https://vercel.com</a>  and create an account. You could also use your social account to sign up.</p>
<p>You will land on a page that will allow you to import a git repository. Connect your Github (or any other git provider's) account, select the repository where you have pushed the code for this project, and click on "Import".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620914322868/QNVeWr95j.png" alt="Screenshot 2021-05-13 at 6.58.14 PM.png" /></p>
<p>Choose to use your personal account when prompted. You will land on the page where you could choose a name for your project and change other settings. All the settings should have been auto-configured correctly and you would not need to change anything. Just click on "Deploy" and let the magic happen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620912603720/Nn-2hIVll.png" alt="Screenshot 2021-05-13 at 6.59.40 PM.png" /></p>
<p>The deployment will start and you'll be greeted with a success message as soon as it completes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620913091448/JqlvzeKfj.png" alt="Screenshot 2021-05-13 at 7.07.22 PM.png" /></p>
<p>Click on the "Visit" button to view the deployed website. For every commit that you push to your repo, Vercel will automatically deploy the latest code on this URL. Vercel will also maintain a live, deployed copy of each of your commits for you to look back (or if you wish to roll back to a previous version). Check out the "Deployments" tab on your project on Vercel dashboard to see deployments corresponding to all your commits.</p>
<h2 id="conclusion-of-the-beginning">Conclusion — of the beginning</h2>
<p>That must feel like an achievement. Tap your shoulder, clap for yourself. You've done a lot.</p>
<p>In the next post, we'll actually start building the portfolio - by adding a navbar, a main hero section and highlight some of our work. Stay tuned for more.</p>
]]></content:encoded></item><item><title><![CDATA[4 ways to perfectly center content using CSS]]></title><description><![CDATA[Centering content in CSS is something that beginners struggle a lot with. CSS provides a lot of options that allow you to center content inside a container. We'll try some of the most commonly used ones.
Centering text
Let's start by learning how to ...]]></description><link>https://blog.rajatkapoor.me/4-ways-to-perfectly-center-content-using-css</link><guid isPermaLink="true">https://blog.rajatkapoor.me/4-ways-to-perfectly-center-content-using-css</guid><category><![CDATA[CSS]]></category><category><![CDATA[HTML]]></category><category><![CDATA[CSS Grid]]></category><category><![CDATA[flexbox]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rajat Kapoor]]></dc:creator><pubDate>Fri, 14 May 2021 09:39:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620984017493/vwv-QyFYm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Centering content in CSS is something that beginners struggle a lot with. CSS provides a lot of options that allow you to center content inside a container. We'll try some of the most commonly used ones.</p>
<h2 id="centering-text">Centering text</h2>
<p>Let's start by learning how to center text in a container</p>
<pre><code><span class="hljs-comment">&lt;!--  our html has a container and text content inside --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container center"</span>&gt;</span>
  this text should be centered
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre><p>We can center the text content using <code>text-align: center</code>. Here's is how our CSS looks</p>
<pre><code><span class="hljs-comment">/* Just to see how big the container is*/</span>
<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">background</span>: black;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">color</span>: turquoise;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">400px</span>;
}

<span class="hljs-selector-class">.center</span> {
  <span class="hljs-attribute">text-align</span>: center;  <span class="hljs-comment">/* horizontally center aligns the text */</span>

  <span class="hljs-attribute">vertical-align</span>: middle;  <span class="hljs-comment">/* aligns the text in the middle of the `line-height` of the text*/</span>
}
</code></pre><p>See it in action:</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/rajatkapoor/pen/VwpvGMZ">https://codepen.io/rajatkapoor/pen/VwpvGMZ</a></div>
<p>If you want to place the text at the center of the screen, wrap it in a <code>div</code> and follow any of the techniques below.</p>
<h2 id="centering-a-div-inside-another">Centering a div inside another</h2>
<p>There are multiple ways to do it. Check out all of these and let me know your favorite one in the comments. For the next few examples, we'll use this common HTML and CSS and highlight only the CSS changes needed to center the contents</p>
<h4 id="html">HTML:</h4>
<pre><code><span class="hljs-comment">&lt;!--  our html has a container which contains a div we wish to center--&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container center"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inner"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre><h4 id="css">CSS:</h4>
<pre><code><span class="hljs-selector-tag">html</span>,
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
}
<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">background</span>: black;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.inner</span> {
  <span class="hljs-attribute">background</span>: turquoise;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
}
</code></pre><h3 id="using-margin">Using <code>margin</code></h3>
<p>We can horizontally center the inner div using margin</p>
<pre><code><span class="hljs-selector-class">.inner</span>{
  <span class="hljs-attribute">margin</span>: auto;
}
</code></pre><p>See it in action 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/rajatkapoor/pen/yLMYQYN">https://codepen.io/rajatkapoor/pen/yLMYQYN</a></div>
<h3 id="using-flex">Using <code>flex</code></h3>
<p>To center this using flex, we need the following CSS:</p>
<pre><code><span class="hljs-selector-class">.center</span>{
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre><p>See it in action 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/rajatkapoor/pen/qBrOJQR">https://codepen.io/rajatkapoor/pen/qBrOJQR</a></div>
<h3 id="using-grid">Using <code>grid</code></h3>
<pre><code><span class="hljs-selector-class">.center</span>{
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
}
</code></pre><p>See it in action 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/rajatkapoor/pen/RwpWqwy">https://codepen.io/rajatkapoor/pen/RwpWqwy</a></div>
<h2 id="conclusion">Conclusion</h2>
<p>This is not all of it. There are many other ways to center content. Post your favorite way of centering content in the comments.</p>
]]></content:encoded></item><item><title><![CDATA[Writing my first custom react hook - useOutsideClick]]></title><description><![CDATA[When react hooks were launched, they completely changed the react ecosystem. I have been using react hooks for quite some time now and I am a big fan. But like a lot of other developers, I have never written a custom react hook. This is mainly becaus...]]></description><link>https://blog.rajatkapoor.me/writing-my-first-custom-react-hook-useoutsideclick</link><guid isPermaLink="true">https://blog.rajatkapoor.me/writing-my-first-custom-react-hook-useoutsideclick</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[webdev]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rajat Kapoor]]></dc:creator><pubDate>Mon, 10 May 2021 14:47:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620657605607/RarlGMNI_.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When react hooks were launched, they completely changed the react ecosystem. I have been using react hooks for quite some time now and I am a big fan. But like a lot of other developers, I have never written a custom react hook. This is mainly because firstly, all the functionality I need is available in a third-party hooks library, and secondly, procrastination.</p>
<p>I am a firm believer in learning by doing. So I am going to create a very simple hook - <strong>useOutsideClick</strong>. This hook will help us to trigger a function when a user clicks outside a component.</p>
<h2 id="where-can-we-use-this">Where can we use this?</h2>
<ol>
<li>Close expanded states of a component when a user clicks outside</li>
<li>Close modals when users click outside the modal</li>
</ol>
<p>and many more</p>
<h2 id="how-will-we-create-this">How will we create this?</h2>
<p>This may not be the best way, but I have been using a very simple approach in my older class-based components. I will just try to replicate that with a custom hook. Here's what we will do:</p>
<ol>
<li>We will add an <code>onClickListener</code> to the <code>document</code> when the component mounts</li>
<li>In this click listener, we will trigger the <code>outsideClickHandler</code> when the target of the click lies outside the desired component</li>
</ol>
<h1 id="lets-get-started">Let's get started</h1>
<p>You can find the final code of this tutorial in this  <a target="_blank" href="https://github.com/rajatkapoor/useOutsideClick">github repository</a> and a <a target="_blank" href="https://use-outside-click.vercel.app/">live working demo here</a> </p>
<p>Let's create a react app and run it using the following commands</p>
<pre><code>npx <span class="hljs-keyword">create</span>-react-app useOutsideClick
npm <span class="hljs-keyword">install</span> <span class="hljs-comment"># to install all dependencies</span>
npm run <span class="hljs-keyword">start</span> <span class="hljs-comment"># to run the app</span>
</code></pre><p>We'll first create the outside click functionality in a simple functional component and then try to extract it into  a custom hook</p>
<p>Let's edit <code>src/App.js</code> to look like:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main"</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre><p>and update the styles in <code>./styles.css</code>  to make things slightly less ugly</p>
<pre><code><span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-id">#root</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.main</span> {
  <span class="hljs-attribute">background</span>: lightskyblue;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">20vh</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">10vh</span>;
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">40px</span>;
}
</code></pre><p>If you check the browser, you'll see something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620575478835/bCHwkGbJd.png" alt="frame_safari_dark.png" /></p>
<h2 id="adding-outside-click-functionality">Adding outside click functionality</h2>
<p>We'll now try to detect when the user has clicked outside the div that says "click me" using the  <a target="_blank" href="https://reactjs.org/docs/hooks-effect.html">useEffect</a>  and  <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html#useref">useRef</a> hooks.</p>
<p>We will start by creating a new <code>ref</code> for the <code>&lt;div&gt;</code> outside which we want to detect clicks</p>
<pre><code><span class="hljs-keyword">const</span> mainRef = useRef();
</code></pre><p>and pass it as the <code>ref</code> prop to the div</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{mainRef}</span>&gt;</span>
</code></pre><p>In our click handler, we will check whether the <code>event.target</code> lies inside the target element. We can do that using the  <a target="_blank" href="https://htmldom.dev/check-if-an-element-is-a-descendant-of-another/"><code>contains</code> function</a>. For now, we will just log if the click is outside the element</p>
<pre><code><span class="hljs-keyword">const</span> onOutsideClick = (e) =&gt; {
    <span class="hljs-keyword">const</span> inMain = mainRef.current.contains(e.target);
    <span class="hljs-keyword">const</span> isOutside = !inMain;
    <span class="hljs-keyword">if</span> (isOutside) {
      <span class="hljs-comment"># call the outside click handler here</span>
      console.log(<span class="hljs-string">"Clicked ouside"</span>);
    }
  };
</code></pre><p>We want to listen to clicks on the whole document as soon as the component mounts or whenever the ref changes. We will do that using the <a target="_blank" href="https://reactjs.org/docs/hooks-effect.html">useEffect</a> hook.</p>
<pre><code>useEffect(() =&gt; {
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    <span class="hljs-comment">// cleaning up the event listener when the component unmounts</span>
    <span class="hljs-keyword">return</span> () =&gt; {
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    };
  }, [mainRef]);
</code></pre><p>Our <code>src/App.js</code> will now be like:</p>
<pre><code><span class="hljs-keyword">import</span> { useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> mainRef = useRef();
  <span class="hljs-keyword">const</span> onOutsideClick = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> inMain = mainRef.current.contains(e.target);
    <span class="hljs-keyword">const</span> isOutside = !inMain;
    <span class="hljs-keyword">if</span> (isOutside) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Clicked ouside"</span>);
    }
  };
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"cleanup"</span>);
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    };
  }, [mainRef]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{mainRef}</span>&gt;</span>
        Click me
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre><p>That's it. We now just need to extract this functionality in a custom hook.</p>
<h2 id="creating-a-custom-hook">Creating a custom hook</h2>
<p>Create a new file called <code>useOutsideClick.js</code>. We will now copy over the code from our <code>src/App.js</code> file to <code>src/useOutsideClick.js</code> and update it to accept the <code>componentRef</code> and the <code>outsideClickHandler</code></p>
<pre><code># src/useOutsideClick.js

<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useOutsideClick = <span class="hljs-function">(<span class="hljs-params">componentRef, outsideClickHandler</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> onOutsideClick = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-comment">// updated this to use the passed componentRef</span>
    <span class="hljs-keyword">if</span> (!componentRef.current) {
      <span class="hljs-keyword">return</span>;
    }
    <span class="hljs-keyword">const</span> inMain = componentRef.current.contains(e.target);
    <span class="hljs-keyword">const</span> isOutside = !inMain;
    <span class="hljs-keyword">if</span> (isOutside) {
      outsideClickHandler();
    }
  };
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"cleanup"</span>);
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"click"</span>, onOutsideClick);
    };
  }, [componentRef]);
};
</code></pre><p>We will now use this inside our app.</p>
<pre><code><span class="hljs-comment">#src/App.js</span>

<span class="hljs-keyword">import</span> { useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;
<span class="hljs-keyword">import</span> { useOutsideClick } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useOutsideClick"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> function App() {
  const mainRef = useRef();
  useOutsideClick(mainRef, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Clicked outside"</span>));
  <span class="hljs-keyword">return</span> (
    &lt;div className=<span class="hljs-string">"App"</span>&gt;
      &lt;div className=<span class="hljs-string">"main"</span> ref={mainRef}&gt;
        Click me
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre><p>And things work perfectly 🎉</p>
<h2 id="example">Example</h2>
<p>We will now update our app to showcase one of the use cases. When the user clicks the blue <code>&lt;div&gt;</code>, we will show more content below it. We will hide this content when the user clicks anywhere outside this button on the screen. We maintain this state in the state variable <code>expanded</code> </p>
<pre><code><span class="hljs-meta">#src/App.js</span>

<span class="hljs-keyword">import</span> { useEffect, useRef, useState } <span class="hljs-keyword">from</span> "react";
<span class="hljs-keyword">import</span> "./styles.css";
<span class="hljs-keyword">import</span> { useOutsideClick } <span class="hljs-keyword">from</span> "./useOutsideClick";

export <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> App() {
  const mainRef = useRef();
  // <span class="hljs-keyword">initially</span> <span class="hljs-keyword">not</span> expanded
  const [expanded, setExpanded] = useState(<span class="hljs-keyword">false</span>);

  // <span class="hljs-keyword">set</span> `expanded` <span class="hljs-keyword">to</span> `<span class="hljs-keyword">false</span>` <span class="hljs-keyword">when</span> clicked outside the &lt;div&gt;
  useOutsideClick(mainRef, () =&gt; setExpanded(<span class="hljs-keyword">false</span>));
  <span class="hljs-keyword">return</span> (
    &lt;div className="App"&gt;
      // <span class="hljs-keyword">set</span> `expanded` <span class="hljs-keyword">to</span> `<span class="hljs-keyword">true</span>` <span class="hljs-keyword">when</span> this &lt;div&gt; <span class="hljs-keyword">is</span> clicked
      &lt;div className="main" <span class="hljs-keyword">ref</span>={mainRef} onClick={() =&gt; setExpanded(<span class="hljs-keyword">true</span>)}&gt;
        Click me
      &lt;/div&gt;
      // <span class="hljs-keyword">show</span> more details <span class="hljs-keyword">only</span> <span class="hljs-keyword">when</span> `expanded` <span class="hljs-keyword">is</span> `<span class="hljs-keyword">true</span>`
      {expanded &amp;&amp; &lt;div className="more"&gt;Lorem ipsum dolor sit amet&lt;/div&gt;}
    &lt;/div&gt;
  );
}
</code></pre><pre><code><span class="hljs-comment">/* src/styles.css */</span>

<span class="hljs-comment">/* add this */</span>
<span class="hljs-selector-class">.more</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
  <span class="hljs-attribute">background</span>: lightskyblue;
}
</code></pre><p>This is how things look now
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620580483969/4JsOXZgYS.gif" alt="CPT2105092244-1680x939.gif" /></p>
<h3 id="summary">Summary</h3>
<p>Hooray! We have written our first custom hook. You could also check out one of the widely used custom hook libraries( <a target="_blank" href="https://streamich.github.io/react-use/">react-use</a>  or  <a target="_blank" href="https://react-hooks.org/">rooks</a> ) and try to recreate one of the hooks for practice</p>
]]></content:encoded></item></channel></rss>