{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/45","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Authentication systems are the backbone of many websites. It allows users to log in to your site and preserving data between visits. It is…","fields":{"slug":"/engineering/website-authentication-protocols/"},"html":"<p>Authentication systems are the backbone of many websites. It allows users to log in to your site and preserving data between visits. It is crucial in offering a robust user experience, which rewards your users for providing their details. Authentications often provide access to personal private data which if made public, it could harm your user. To prevent these, authentication protocols were created to secure the requests while allowing users to still safely login to your system from any environment.</p>\n<p><strong>Basic SSL Auth</strong></p>\n<p>Basic auth is the simplest form of web authentication. It utilizes standard HTTP headers in place of more complicated solutions that rely on cookies, session identifiers, and login pages. There is very little security built into the basic auth system. Credentials are transmitted with only Base64 encoding and are not encrypted or hashed. Due to the ingrained insecurities in the system, these requests are most often made via HTTPS.</p>\n<p>The authorization information should be compiled into the following format and included in the header:</p>\n<p>Format:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"http\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&lt;!--Authorization: Basic --&gt;</span></code></pre>\n<p>Full details on the Basic Authentication protocol can be found here: <a href=\"http://www.w3.org/Protocols/HTTP/1.0/spec.html#AA\">Authentication Protocol</a></p>\n<p><strong>Digest Auth</strong></p>\n<p>Digest Auth works similar to basic SSL authentication with the exception that the password is encrypted using a one-way hash. It utilizes MD5 cryptographic hashing with a nonce(a server-generated value that prevents replay attacks).</p>\n<p>The typical flow of a Digest Auth request is :</p>\n<ol>\n<li>A user navigates to a page that requires user authentication.</li>\n<li>The server responds with a 401 message that signifies that a user is not currently authorized to access the content. In the response, it also includes the nonce which will be used during the authorization to prevent replay attacks,</li>\n<li>The site then displays an authentication interface to gather the required details( username and password )</li>\n<li>The provided details are re-sent to the server with an authentication header included in the request that has a response code.</li>\n<li>The server would then verify the provided credentials and accept the authentication or return a 401 message if the credentials are incorrect, which would cause the user to be again prompted with the authentication interface.</li>\n</ol>\n<p>You can find full details on the Digest Auth protocol can be found here: <a href=\"https://www.ietf.org/rfc/rfc2617.txt\">Digest Auth Protocol</a></p>\n<p><strong>OAuth 1.0</strong></p>\n<p>The OAuth 1.0 protocol relies on having a shared secret between the server and the site. This shared secret is used to generate a signature that is included in the request. The generated signature is used to verify the validity of the authentication request on the server-side. The process for authorizing the user is generally handled in three steps (3-legged OAuth):</p>\n<ol>\n<li>Site obtains Request Token.</li>\n<li>User authorizes the Request Token.</li>\n<li>Site exchanges Request token for Access Token.</li>\n</ol>\n<p>The process of completing a 3-legged OAuth request will generally be handled as follows:</p>\n<ol>\n<li>\n<p>The site will send a signed request for the Request token. This request should contain the following parameters:</p>\n<ol>\n<li>oauth_consumer_key</li>\n<li>oauth_timestamp</li>\n<li>oauth_nonce</li>\n<li>oauth_signature</li>\n<li>oauth_signature_method</li>\n<li>oauth_version</li>\n<li>oauth_callback</li>\n</ol>\n</li>\n</ol>\n<p>This request will be validated on the server.  If validated, it will return the request token in the following format:</p>\n<ol>\n<li>oauth_token</li>\n<li>oauth_token_secret</li>\n<li>and any other additional parameters returned by your server.</li>\n<li>The next step after retrieving the request token is to prompt your user to input their login credentials. These are then formatted into a signature with the oauth_token request token. Then they are sent with a request back to the server for validation. Upon successful validation from this request, the server will return the following:</li>\n<li>oauth_token</li>\n<li>oauth_verifier</li>\n</ol>\n<p>These will be used in the next step to retrieve an access token.</p>\n<ol>\n<li>The final step is exchanging the retrieved details from step 2 for an access token, which will be used to access the server's resources. To exchange your request token for an access token, you can make a request to the server with the following signed request</li>\n<li>oauth_token -returned from step 2</li>\n<li>oauth_consumer_key</li>\n<li>oauth_nonce</li>\n<li>oauth_signature</li>\n<li>oauth_signature_method</li>\n<li>oauth_version</li>\n<li>oauth_verifier -returned from step 2</li>\n</ol>\n<p>This will return you an access token to be used in conjunction with your secret in order to make requests for information from the server.</p>\n<p>You can find full details on the OAuth 1.0 protocol here: <a href=\"https://tools.ietf.org/html/rfc5849\">OAuth 1.0 protocol</a></p>\n<p><strong>OAuth 2.0</strong></p>\n<p>This is similar to the OAuth 1.0 protocol, it relies on a client id and secret in order to format request, but simplifies much of the complicated signing process that is inherent in the OAuth 1.0 system. The process for authorizing a user using the 3-legged OAuth 2.0 protocol is as follows:</p>\n<ol>\n<li>\n<p>User is directed to the service for authorization with the following details included in the authorization URL:</p>\n<ol>\n<li>client_id</li>\n<li>redirect_uri</li>\n<li>response_type</li>\n<li>scope</li>\n</ol>\n</li>\n<li>\n<p>The user would then authenticate with the service and grant the application access to their details. On successful authentication, the user is redirected back to the redirect_uri with the following parameters:</p>\n<ol>\n<li>code</li>\n<li>state</li>\n</ol>\n</li>\n<li>\n<p>The code returned in step 2 is then used by the application to make a request for an access token. Included in this request should be:</p>\n<ol>\n<li>client_id</li>\n<li>client_secret</li>\n<li>code</li>\n<li>redirect_uri</li>\n<li>grant_type - This should be set to “authorization_code”</li>\n</ol>\n</li>\n</ol>\n<p>The server will verify these details and then return an access token with an expiration time if they are valid. These get generally returned in the following format:</p>\n<ol>\n<li>access_token</li>\n<li>expires_in</li>\n<li>refresh_token</li>\n</ol>\n<p>You can find full details on the OAuth 2.0 protocol here: <a href=\"http://oauth.net/2/\">OAuth 2.0 protocol</a></p>\n<p>Authentication protocols allow you to secure your data with varying levels of security. Depending on the data being accessed and your desired level of security, implementing one of the above protocols allows you to be confident that your data is safe and can only being accessed by users that are permitted to your system.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"December 01, 2015","updated_date":null,"description":null,"title":"Website Authentication Protocols","tags":["Authentication","Oauth"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5625,"src":"/static/2777d4b53aa6128513f070b7f78f3651/ee604/server-proc-150x150.png","srcSet":"/static/2777d4b53aa6128513f070b7f78f3651/69585/server-proc-150x150.png 200w,\n/static/2777d4b53aa6128513f070b7f78f3651/497c6/server-proc-150x150.png 400w,\n/static/2777d4b53aa6128513f070b7f78f3651/ee604/server-proc-150x150.png 800w,\n/static/2777d4b53aa6128513f070b7f78f3651/f3583/server-proc-150x150.png 1200w,\n/static/2777d4b53aa6128513f070b7f78f3651/5707d/server-proc-150x150.png 1600w,\n/static/2777d4b53aa6128513f070b7f78f3651/6e0a6/server-proc-150x150.png 2256w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"1. Nim Game Click to View Original Question This question is very easy once you figure out the trick behind the game.\nSince each time you…","fields":{"slug":"/engineering/nim-game-add-digits-maximum-depth-of-binary-tree/"},"html":"<h3 id=\"1-nim-game\" style=\"position:relative;\"><a href=\"#1-nim-game\" aria-label=\"1 nim game permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Nim Game</h3>\n<p><a href=\"https://leetcode.com/problems/nim-game/\">Click to View Original Question</a></p>\n<p>This question is very easy once you figure out the trick behind the game.\nSince each time you can only pick 3 stones at most, if there are 4 stones originally on the table, no matter how many you take ... your hopefully non-stupid friend can easily beat you. The same logic also applies when the number of stones is more than 4.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">n</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{boolean}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">canWinNim</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">n</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">n</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">4</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> ? </span><span class=\"mtk4\">false</span><span class=\"mtk1\"> : </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"\" style=\"position:relative;\"><a href=\"#\" aria-label=\" permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\n<p>2. Add Digits</p>\n<p><a href=\"https://leetcode.com/problems/add-digits/\">Click to View Original Question</a></p>\n<p>This is a tricky question, the key is trying to find the repetitive pattern of the Digits Sum. If you can't get the pattern by observation then we can do some math to find the pattern.</p>\n<p>So assume we have a 4 digit number \"abcd\" or 1234, and we want to find out the sum of the digits which in expression is:</p>\n<p>var digitSum = a + b + c + d</p>\n<p>We still can't figure out the answer from this alone, so we need to find something else to help us to get the value. Then we can consider the actual value of \"abcd\" = 1000a + 100b + 10c + d.</p>\n<p>- If you're familiar with Ring Theory (pretty sure it's Ring Theory.. I could be wrong..) then perfect! Under Ring 9, the actual value of abcd === a + b + c + d.\n- And if you don't know about Ring Theory, think of this as getting the remainder of \"abcd\" divided by 9</p>\n<p>> (1000a + 100b + 10c + d) % 9 => (999a + a + 99b + b + 9c + c + d) % 9 => a + b + c + d</p>\n<p>So whatever the reminder is equals to the sum of the digits and that is more than enough information to solve the question.</p>\n<p><strong>Be careful with the number 0 !!</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">num</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addDigits</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">num</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">num</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\">) </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">num</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">num</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">9</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> ? </span><span class=\"mtk7\">9</span><span class=\"mtk1\"> : </span><span class=\"mtk12\">num</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">9</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"-1\" style=\"position:relative;\"><a href=\"#-1\" aria-label=\" 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\n<p>3. Maximum Depth of Binary Tree</p>\n<p><a href=\"https://leetcode.com/problems/maximum-depth-of-binary-tree/\">Click to View Original Question</a></p>\n<p>This is very typical of recursion problems, and recursion is always hard to explain in words</p>\n<p>(╯‵□′)╯︵┻━┻</p>\n<p>Regardless I will try my very best to describe it.</p>\n<p>1. You have a tree node, and check if it is an empty tree, if so return 0\n2. If it is not empty, use recursion to find the value\n3. The recursion will start with the left node of root, and iterate through the tree, and keep checking the depth of each node till reaching out to the leaves. Each node (small root) records its maximum depth value by a record count called \"\"currentLength\"\".\n4. Until the whole tree is traversed, the root will compare its leftLength and rightLength and return the answer!</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">rightLength</span><span class=\"mtk1\"> ? </span><span class=\"mtk12\">leftLength</span><span class=\"mtk1\"> : </span><span class=\"mtk12\">rightLength</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rootLength</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}--&gt;</span></span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"November 24, 2015","updated_date":null,"description":null,"title":"Nim Game, Add Digits, Maximum Depth of Binary Tree","tags":["Nim","JavaScript"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/e9162a5f9c634d0d0932d5bc4a18b24e/6d161/nim-blog-150x150.png","srcSet":"/static/e9162a5f9c634d0d0932d5bc4a18b24e/6d161/nim-blog-150x150.png 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Lucius Yu","github":null,"avatar":null}}}},{"node":{"excerpt":"As a preface to this article: preprocessors can be used for a variety of file types, but this article is going to focus solely on CSS…","fields":{"slug":"/engineering/the-truth-about-css-preprocessors-and-how-they-can-help-you/"},"html":"<p>As a preface to this article: preprocessors can be used for a variety of file types, but this article is going to focus solely on CSS preprocessors. Additonally I'm going to try and avoid my personal bias and give a very generic description of CSS preprocessors rather than my preferred preprocessor.</p>\n<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>First off what is a preprocessor? To give you a simple analogy think of speaking with someone, in a language you understand, who has a strong accent or is speaking in a different dialect. They're technically speaking the same language as you, but actually understanding what they're saying can be next to impossible.</p>\n<p>In the context of CSS, the \"normal\" or unaccented language would be CSS and the accented version would be the preprocessor! What this means in practice is that you're writing out expressions that resemble standard CSS, but with some very distinct differences with regards to its syntax.</p>\n<p>As with regular spoken language, there's not a whole lot we can do with something we can't understand. Luckily there are translators, and the same is true of preprocessors. The preprocessor code can be processed (there are a number of different ways to accomplish this), and then out pops an understandable standard-syntax CSS file ready to be used.</p>\n<p>Now why would we want to write CSS in some weird way you might ask? An excellent question! Because our nonsense can be translated into regular CSS, this allows us to write some very robust and even dynamic CSS expressions.</p>\n<h2 id=\"new-toys\" style=\"position:relative;\"><a href=\"#new-toys\" aria-label=\"new toys permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>New Toys</h2>\n<p>With preprocessors we've got a bundle of features now available to be used along with all the standard CSS rules we're accustomed to writing.</p>\n<p>To name a few features supported by preprocessors we've got: functions, mixins, math, variables, operators, conditionals, iteration and more to help you be more organized and write less overall.</p>\n<h3 id=\"variables\" style=\"position:relative;\"><a href=\"#variables\" aria-label=\"variables permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Variables</h3>\n<p>Variables increase your maintainability drastically by making it so you only have to change a value in one place to affect it everywhere it was used. Imagine for example you want to add a Halloween theme to your site's colors.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> </span><span class=\"mtk6\">p</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">black</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementTwo</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">h3</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">black</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">a:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">:</span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Changing them back would require you to go and change each instance of black or orange. However; with variables you can do something like this.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">$</span><span class=\"mtk4\">theme-color-1</span><span class=\"mtk1\">: orange;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">$</span><span class=\"mtk4\">theme-color-2</span><span class=\"mtk1\">: black;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> </span><span class=\"mtk6\">p</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-2;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementTwo</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">h3</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-2;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">a:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Define the value of the variable in one place, and everywhere it gets used will be a reference to that value. Want to change all instances of black back to grey? Just change the variable definition and you're done.</p>\n<h3 id=\"functions--friends\" style=\"position:relative;\"><a href=\"#functions--friends\" aria-label=\"functions  friends permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Functions &#x26; Friends</h3>\n<p>Another one of the biggest features would be functions. With these you can set up one well written function definition and then sit back and let it do all the heavy lifting for you!</p>\n<p>Functions combined with math, variables, iteration, and conditionals allows you to write some very dynamic style rules. Think of sprite sheets where the value of the background position is being incremented with each statement. Instead of writing out each one by hand, make a function that uses math and iteration to change the background position.</p>\n<p>That's a very simple example, but I've seen some truly impressive and complicated designs created with the use of functions!</p>\n<h3 id=\"selectors\" style=\"position:relative;\"><a href=\"#selectors\" aria-label=\"selectors permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Selectors</h3>\n<p>One of my favorite features of preprocessors are the new selectors. The parent reference (&#x26;) allows you to group your rules so that everything pertaining to a specific element can be grouped together nicely.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    &amp;:hover {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">color</span><span class=\"mtk1\">: some-color;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Compiles to...</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.someElement:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: some-color;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The parent selector takes whatever follows it immediately and tacks it on to the parent that it is nested under. In this case hover will be appended to .someElement. Another great one to check out is the root reference!</p>\n<h2 id=\"nesting-and-general-aesthetic\" style=\"position:relative;\"><a href=\"#nesting-and-general-aesthetic\" aria-label=\"nesting and general aesthetic permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Nesting and General Aesthetic</h2>\n<p>CSS's default format is ugly as sin. An endless tide of barely indented rules, hopefully organized in some meaningful way. With CSS preprocessors nesting is an awesome feature that helps your rules become more intuitive/logically grouped and increases readability. Nesting can give your CSS a much more distinct visual hierarchy not unlike HTML.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    .someOtherElement {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        some-rule: another-value</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Compiles to...</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> </span><span class=\"mtk6\">.someOtherElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: another-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Full disclosure, your resulting CSS file will still likely look like someone dropped their bowl of Alphaghetti in their bowl of Alphabits and then threw that bowl at a wall. However; the file you actually work in will be considerably prettier, and that's all we care about.</p>\n<p>Some people have beef with preprocessors because of over done selectors which are a result of going a little too hard with nesting. An easy way to avoid this is by limiting your nesting to 3 levels deep. Any further than that gets pretty ugly, but hey I'm not your supervisor... if you feel it's necessary then you do what you gotta do.</p>\n<h2 id=\"processing-dependant\" style=\"position:relative;\"><a href=\"#processing-dependant\" aria-label=\"processing dependant permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Processing dependant</h2>\n<p>Now depending on how you choose to have your preprocessor code processed these features may or may not be more/less accessible. That being said I still feel they are worth mentioning.</p>\n<p>Auto updating the page you're working on is a small perk but I remember being quite happy to find out I could just save my project and not have to spam F5 like my little sister trying to buy front row Justin Bieber tickets online. Just save and it will update your project automatically.</p>\n<p>Another one is vendor prefixes. There are a handful of ways to stop writing these things out by hand each time. Whether it's via mixins, functions or a built in feature of the processor itself you can avoid writing out these dreadfully monotonous prefixes for good.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>At first it might seem like a bunch of new stuff you have to learn and implement... but really if you already know CSS you're over halfway there. All you need to do is learn the specific syntax and familiarize yourself with the new features available to you with the preprocessor of your choice. It's a gentle learning curve with a surplus of benefits to integrate preprocessors into your workflow.</p>\n<p>This article is by no means all encompassing, but rather a sampler to create enough interest to try it out and learn more about preprocessors.</p>\n<p>On that note there are <a href=\"http://csspre.com/compile/\">resources</a> for comparing the preprocessors as well as trying them online. Each one has its own perks so try 'em out and find the one that fits your style!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n</style>","frontmatter":{"date":"November 17, 2015","updated_date":null,"description":null,"title":"The truth about CSS preprocessors and how they can help you","tags":["CSS"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/06a5f244323a7617c371dd411e68c861/6d161/desdev-150x150.png","srcSet":"/static/06a5f244323a7617c371dd411e68c861/6d161/desdev-150x150.png 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Zakary Hughes","github":null,"avatar":null}}}},{"node":{"excerpt":"In this blog, I will cover some of my favorite Sublime features. Use of these plugins will dramatically reduce the amount of tedious tasks…","fields":{"slug":"/engineering/beginners-guide-for-sublime-text-3-part-2/"},"html":"<p>In this blog, I will cover some of my favorite Sublime features. Use of these plugins will dramatically reduce the amount of tedious tasks you have to perform, and make your worktime really fun. I will start with some of the most basic features that come with fresh installation of Sublime. There are lots of good tutorials on Sublime shortcuts and plugins on the internet, but I feel there should be more about these fundamental features. I have seen many people who are familiar with the plugins but not with these cool built-in features. In this article we will be introducing \"Snippets\", \"Project\" and \"Macros\".</p>\n<p>Here we go:</p>\n<h3 id=\"snippets\" style=\"position:relative;\"><a href=\"#snippets\" aria-label=\"snippets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Snippets</h3>\n<p><img src=\"/3e21aab686b29a54a248ccd545aca465/snippet-demo.gif\" alt=\"snippet-demo\"></p>\n<p>Back when i introduced Sublime editor to my friends,\"Snippets\" was among the first few features which really intrigued them. To give a quick peek what a snippet looks like:  </p>\n<p>This is definitely the feature you will use the most! To start using snippets, you can either create your own snippets according to your needs or download some ready-made snippets created by others to fulfill some generic coding needs. Like the one I demonstrated, it is pre-made from a plugin called <code>Html Page Snippets</code>, and command <code>docjq</code> will create a boiler template for a Html page that contains bootstrap and jQuery.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 113.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC5klEQVQ4y8WTWU8TURiG+0sMBQqddrrM3oF2SktZ2lIWMeBaExXFQlFAIwkhaqKG6CUGA0QWwZa1BWY67Uw7nemGa0xMiFwYL/TC3+GRJmggpiQmmjwXJ1++57zfOSdHtcYlw1Ge5VMJURFEJSHI25zIxVJbrJAQQCWbTCoLkdzYdGY5KvHxNC9kRKnA8emUlFeNB4ceBIfujNx9/2F399Pnvb0v375+V+T8WX/PtcBQIHjrUk/w6eQMHxMWQxGWlyXl9au3HzO5d6NjD1WTTe5xh8vlcD9+MjE7MTUzOftsav7e/UdGpMaI2kyYrUqH998ciXDJjS1hfTPOi5l09k1CyvnaT6voxjbS6dWbLEYj2mSxuAnCSmEMgzsdNIYTlIXSQvDVwODKBre0HI2yopDOA3OTExvd7ar6hla7w2Mw0xRNNdbXeehal91uwigUJwmSsjFWvcHY2zc8v7Q2Mxfa5lMpZYeNS9OzL5u8nSpHg8/m8IAhNVqkGiZhpBazOBGyzkTYjZgNJZ06Iz0wPBrlxLnFtfA6K0h5MV2Ip7ItHWcOZBo2URaEpnArQtrNODit1YxbUcquhYne/tuh1e25xfWFUATskpR3Eum8t60byK1ARggGxZlatIYy0xBMQjBRRG+gyioMvf3DvKCE17ZWN1hRyiXlfExIN3tPFZO9EIyDsSsgpBJCqnXoAaB+Qg0F+ociUXbhRTgWE2Q5pyg5Wc66vSd/yaBVu88RWRfoG+S2Yyvh1ZSYysqZzD6H5aP8lMt1vddvsFvs85nZcGhZlmQpKWWVrKel8xiyGgoODPMcD5IL+cJOYQcAkps9HSVkrR6rrDYxjuau7gtd3X7/xZ4L/iuAc+cvo4SthFwE+GqNQV1pKKvQF1FXwlUQUnyqEjLIBw2HAPVjyX/ib2Xff0v+h2ODmwf8nuyp1mEarUmjNZekospYrjEU1yqHy8c4W1CSQQhbScAPt1gbnC4fRtoBPwBdFbML4QCTewAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"new-snippet\"\n        title=\"new-snippet\"\n        src=\"/static/1eaf59408b9d1b244c17eefe6b8d4c53/e5715/new-snippet.png\"\n        srcset=\"/static/1eaf59408b9d1b244c17eefe6b8d4c53/a6d36/new-snippet.png 650w,\n/static/1eaf59408b9d1b244c17eefe6b8d4c53/e5715/new-snippet.png 768w,\n/static/1eaf59408b9d1b244c17eefe6b8d4c53/b5a09/new-snippet.png 1360w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>To create your own snippet, go to \"Tools\" => \"New Snippet\", an interface to create your own snippet will pop up, it would look something like this:  </p>\n<ul>\n<li>Replace the default line with your snippet, the default one looks like this:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Hello, ${1:this} is a ${2:snippet}.</span></code></pre>\n<p>Note: The dollar sign \"$\" allows you to use tab key to jump between, so set it wisely!</p>\n<ul>\n<li>Uncomment this line to set up a tab trigger for the shortcut</li>\n</ul>\n<p>Now save it, but keep in mind putting it in the correct location is important!</p>\n<p>If you can not find it, go to \"Sublime\" - > \"Preferences\" -> \"Browse Packages\", and create a folder called \"User\" if there isn't one already, and save it there.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 67.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACWUlEQVQoz5WQ708ScRjA759QRF8IvgAEFj8PJGLOUvSQTQFXluvX5qrpuwxfWLn0RfaimmtFA0GOODjwDu5AOBQw8u7krsu01j/UF1ys2Wrrs2fPnu37/Xyf5/tAz7HjF2lpNS5uU0326OuR9IPjj/nmiSh9Fz5/a4qnIATx9Kh5LAgnHCeBmmXF2gHH8hLUZBs7eJomiXKRFnheEoXZ2Vm/z4cgE2Ojo+NuN8jIxATi8SAIMunxeCc9Xq93HBy43dDK+/p6rP5sq/4kcvg0yq+Ga/P3F2/fuXt97lZg5tr8vQfTvkBXV7esuxU9MlmfvKe3t0+pVMrlcmgjtv8O/xgm+ZcYu4E2XicPqN1qZocm8iUMJz9xYhLPOIcvuUYuD18ZNZrNRhMIk0ajGRwchJgyk0rhuRzFMEylzBToIp7Nv9oMReNYFMUanLi1HR8ZG7HCNgsMw0ND9otOm8Oh1eq0Wi2EE4VQBN2Kp+hSjaAZLEtRxQqKZZNpIkPSRaYaCkcdDgcQbTab2WwG2W63g2y1WqFSpU5QpUKpulc/rDd4ptqgdivbiXQMTQE/S9KxRNLepiXAVqC23oFho9EABWauTvsDUz7/1LTf55+5MXczS+aJHOi5V6keHPLNzTdvwYRqtVrTBhTgtyCrVCpIr9NdaGMwGMAll8uVy+fjaAJNfEjhuCh9CUciwAFX1X8AWSytRZwBaqfT+XhlZXk5GAw+Wlp6uLa+trC40Gl7DshkMll+A6xEp9Pp9fqBgQGFQtHf369QKDV/4bzcGQT42l/8h3zGP5wOPwH2xiZDG4OaRAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"browse-package\"\n        title=\"browse-package\"\n        src=\"/static/11a66afdbf80d36eaa9f4b484c95470e/e5715/browse-package.png\"\n        srcset=\"/static/11a66afdbf80d36eaa9f4b484c95470e/a6d36/browse-package.png 650w,\n/static/11a66afdbf80d36eaa9f4b484c95470e/e5715/browse-package.png 768w,\n/static/11a66afdbf80d36eaa9f4b484c95470e/e5ca1/browse-package.png 1332w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"project\" style=\"position:relative;\"><a href=\"#project\" aria-label=\"project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project</h3>\n<p>Using \"Project\" feature to organize your projects is super easy and handy. It saves a lot of time that you'd normally waste finding different folders and then dragging and dropping to your Sublime each time. Additionally, it saves your previous location so you can just pick up where you left off. Let's see a quick demo:</p>\n<p>Saving and using your projects is very straightforward.</p>\n<ul>\n<li>First drag some folders and files that you want to open into Sublime</li>\n<li>\n<p>Then go to the menu, click \"Project\" -> \"Save Project As\"  </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 87.53846153846155%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADCklEQVQ4y31T604TQRjdp4BEEloo7d63uzOz9xvdbgsKMQokGh9ANCbcQawkGhMfwAfwB4FwU2ClpS2UOwgmyjv5bQsJ/NCT2Wl3mjPnfOf7Sq0tL29G1b3GSb1xUqkdlKuNWuMY9kr9sL5/uBidfVk/36wcXFxdn19d1xqna9+jrajSODqr7R9RQa8XBIHnur7nwcIYe47TVyzAiSiK70ulaDtaXFot7+6dnl/9/PVnamYunUkLgsALPJVzTNd1JUkSm+hOpZDAODgrCGJ7e9voqzer36Kvi8tbUXm31gDBl6Ov29rakl1dnYkEFTrayGBBVhBC8cNxPBK5nOcSTed5fnJ6trp3uBmV642j3frB8dnl+OR0VzIJP7EsS2GMir7tOK5KCJDhNJPJFB8O9D8axKo2M/dua6e6tLKxtrH1o1I/Pr8cG59MJhMcxzEMQyGEiar6vm/bNiEkvpKm84U+WB0dDyamZrZ3akBeWd8sV/cvrn7Pzs0nEp03ZEhIVVXHcTRNUxQFSmVoOgiLhmmmUqmnQ8Ozb0tjE1PzpYXSwoePnz4PDY/AOXhuKisKkF3XM02rSRY4liOagYhGsyzk191EV4wkoKenh7kFlc1mDcMoFIr5IIASwDaShLytF12jV80SWYQIQYe7RUvzhgxquq67EC8hLWWQfjw48GSgr98l8J35NyhZUaBaGI8WWYxrZjzfL4ZBTlf+R23VbOg6pA2jAuGBMBgDcpjzciaS+Ht0sHz3nTI14lmGAg0jGPrcnDshK8uKyOkSh0Q+naEhuQzDwGcPTCYd41b5PnhBxLKU8+xcWPCDfM61864Z2AYMUug7vo4tRZBFoUWPA7vDjQOTBFGRRAJJGKaqaZAFGAFbhqapGArhwNxNn++TQVkAZmCRPgsHBir4lm+qoYFVhNIMS7MwBGBO5Hjunm1IC/Ys/LN4dtjHzwM1MPFQ6DwLjRehMZy34C6PSLIUt49v9jseEnAFm9RcwIbBsHA2XhoxCbJVxdMUT5UdFVlYVgROZGmeyaTT6b9jGyDPrkScaAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"save-proj\"\n        title=\"save-proj\"\n        src=\"/static/1d33a60947256a60d36a7a16d86e4645/e5715/save-proj.png\"\n        srcset=\"/static/1d33a60947256a60d36a7a16d86e4645/a6d36/save-proj.png 650w,\n/static/1d33a60947256a60d36a7a16d86e4645/e5715/save-proj.png 768w,\n/static/1d33a60947256a60d36a7a16d86e4645/019a6/save-proj.png 1818w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>Note the extension is \".sublime-project\" and you may want to put all your project files in one central location</li>\n</ul>\n<p>That's it! You're done! Super easy right?</p>\n<h3 id=\"macros\" style=\"position:relative;\"><a href=\"#macros\" aria-label=\"macros permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Macros</h3>\n<p><img src=\"/e8a218bdc92e2c8c118faeb6fec384e0/without-macro.gif\" alt=\"without-macro\"></p>\n<p>Do you always feel frustrated by repeating the same tedious task again &#x26; again? Hmm... at least that's how I feel when I need to covert a vertical line of data into an array. Tasks like these are pretty common when you need to copy a line of data from spreadsheets. Using shortcuts, the best way I can come up with to accomplish this would be like so:  </p>\n<p>It takes about 8 shortcuts to finish each process, that's including the first paste action and then adding a space character after each comma. Imagine having to do this for each line of a table, and for every single spreadsheet you have to work on. It would be hundreds of shortcuts you need to press and each time you are just repeating the exact same sequence of keys.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 73.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB60lEQVQoz42SO2/aUBTHmZu5eQw4ahEIItqqhrIWGNKhjSAhaYmdoSoPp2lIJSBT+hX6EapUCiY2MsQBbONr+/ptnh+qV3RB7YB/w9E9R/qd/xluQOv3eL5vmGPPW7ju3PXmhuk6zhQ9UOs4s7E35aTZT3r6OHI0aGu6ZzkzBbqWPQ2c5A+Oj48KhUI+l8svOTo8zOVymUwmnU5ns9lUKvXj5kbXtPY9OxSACi1vshhPFpe1q8CLl69e43g8Ht9bIRqNbm1vP93c3NrZebKxQZBngqRwvX63NxiKYASgqtvvPxwEEjieSCSSyeSbFVAbi8XQCrQIw7BSqfLwKLTabPehj0xxpA4lcPKxGMCX8j+g4apcrlD8QKIZTpBUWTVR7XC8X7lUriL5122rzXASSgYQaNanIrFe3t3FPn8pobPvaOaOZvmBKCu6bo2Lp4Sf5GC1SgHVYDpdrscDVVc0Q4Wmr2R0NkVRsiwzDCuKoq7rEEL0K0iSXC8HMeycqgJR6HYYCGQbolxlYlskcepLpiplIAxav28797ShyFCW5q59Rvg4OxgMfvt6rskjjmU805g4lmeZM9cl18qohkKhd/v732u1y4uL60ajWa836vXrZjOdfrtG/ks4HH6+5NkKkUjEl4zee/+Bhn8A5NVCgeRFjYMAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"start-macro\"\n        title=\"start-macro\"\n        src=\"/static/2387091fee10d76618c295145185f7f3/0a47e/start-macro.png\"\n        srcset=\"/static/2387091fee10d76618c295145185f7f3/0a47e/start-macro.png 600w\"\n        sizes=\"(max-width: 600px) 100vw, 600px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Well you might think there must be a better way! You bet there is! \"Macros\" are designed to handle this kind of nasty situation and save you from all that boring work. Here I made a very quick and easy example, it converts a vertical line of data into an array:  </p>\n<p>Magic! Lots of time and lives will be saved by this little gadget. So now, how to make your very own macros. First of all I would recommend trying out your set of operations several times to make sure it will get recorded correctly. When you are ready, open a new window/tab in Sublime, clear your mind, take several deep breaths, and here we go.</p>\n<ul>\n<li>\n<p>Go to \"Tools\" -> \"Record Mac  </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 73.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB60lEQVQoz42SO2/aUBTHmZu5eQw4ahEIItqqhrIWGNKhjSAhaYmdoSoPp2lIJSBT+hX6EapUCiY2MsQBbONr+/ptnh+qV3RB7YB/w9E9R/qd/xluQOv3eL5vmGPPW7ju3PXmhuk6zhQ9UOs4s7E35aTZT3r6OHI0aGu6ZzkzBbqWPQ2c5A+Oj48KhUI+l8svOTo8zOVymUwmnU5ns9lUKvXj5kbXtPY9OxSACi1vshhPFpe1q8CLl69e43g8Ht9bIRqNbm1vP93c3NrZebKxQZBngqRwvX63NxiKYASgqtvvPxwEEjieSCSSyeSbFVAbi8XQCrQIw7BSqfLwKLTabPehj0xxpA4lcPKxGMCX8j+g4apcrlD8QKIZTpBUWTVR7XC8X7lUriL5122rzXASSgYQaNanIrFe3t3FPn8pobPvaOaOZvmBKCu6bo2Lp4Sf5GC1SgHVYDpdrscDVVc0Q4Wmr2R0NkVRsiwzDCuKoq7rEEL0K0iSXC8HMeycqgJR6HYYCGQbolxlYlskcepLpiplIAxav28797ShyFCW5q59Rvg4OxgMfvt6rskjjmU805g4lmeZM9cl18qohkKhd/v732u1y4uL60ajWa836vXrZjOdfrtG/ks4HH6+5NkKkUjEl4zee/+Bhn8A5NVCgeRFjYMAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"start-macro1\"\n        title=\"start-macro1\"\n        src=\"/static/2387091fee10d76618c295145185f7f3/0a47e/start-macro1.png\"\n        srcset=\"/static/2387091fee10d76618c295145185f7f3/0a47e/start-macro1.png 600w\"\n        sizes=\"(max-width: 600px) 100vw, 600px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>Do your operations</li>\n</ul>\n<p>Usually you would have something copied in your clipboard, so it could start with a \"Paste\" command. Now it's your time to shine, do a clean and precise set of operations to format the data.</p>\n<ul>\n<li>\n<p>Stop your macro  </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 78.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAACPElEQVQoz3WS22/SYBiH+QPmpdzaSgasJhu0w6gX88qVecsNLPGKk/FGF6Nu46SJ2fRmGU5jXIyZEYaU0gOltbT9Wk5zbAkG0MzDX+M3BAICT95++drmyft7+9VklHW1ftRs/uh8//OtddZq/zo5bbXaP+Et3Lc7vzuds/dc6/HbhgyOjcqxXm6Uq6ea8RW+NYVDd/z3guHQ3UAgGAyGgoFQOBT2+/1er9fn9a36Vj0ez/67fYEXMp/polgyyvXGSROuD+6vmebnFxwLjjkMm+uBwf2sdfZiF7PZPHNhZu3ho4KoMJwIS5KBCirSF+3a9RsmArIIcS26ugUv11UnjtvtdpvNBlcEQdY3oiwnZnMsV5BkRZdkjRfkW8ukCYcQxHnh/SIIh9Np7wKToCi6uRlLpalMNl+UFEU1BLH06ZAiSXdXxodkYpIcjVM09+EgnWcFBWYuAYYrDsn41M6XUfTJeoSi+XSGhsUXSwqoqqA62nkQHsqOgYzBzpFoXJTUXJ6naDZLMYIow7GXezMPAo/FxrBzOZ5IMAyXSh0WCkUAdF03gKa73f/FJsbk7syJWFRgWZbOlYFW1UEFaIamut3klNijciyyIfJs+uMBl89VNMVQ5JoO3CQ51nl0ZhgbnvPzZ09BSeaZ/FHFaNSrjVqlpuu3V1b65zz9a1sslqDf/3J7+8XW1pu9V6+Tyb3k7u7Ozs2lpaGfZFLsf0Af9kcR5BIE6WG1WsfOmZggY32uDMAw+Hys8yR5Gn8B3ZNS+eilX44AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"stop-macro\"\n        title=\"stop-macro\"\n        src=\"/static/d4f4fae1e0e00915e1b1ae2c8845c33d/0a47e/stop-macro.png\"\n        srcset=\"/static/d4f4fae1e0e00915e1b1ae2c8845c33d/0a47e/stop-macro.png 600w\"\n        sizes=\"(max-width: 600px) 100vw, 600px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>Playback</li>\n</ul>\n<p>You can find it under the same \"Tools\" menu. Just use it to make sure it did what you want, sometimes even though you recorded it properly, the macro doesn't recognize the operations correctly. For this reason it's important to make sure everything is correct and smooth, and if it's not, try find some alternatives for your operations.</p>\n<ul>\n<li>Save It!</li>\n</ul>\n<p>Similar to other Sublime tools, it will be saved with an extension called \".sublime-macro\", after it gets saved you will be able to find it in your Macro User List.</p>\n<h3 id=\"to-be-continued-\" style=\"position:relative;\"><a href=\"#to-be-continued-\" aria-label=\"to be continued  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>To Be Continued ..</h3>\n<p>I hope you had fun and learned something new about Sublime. Next time we will cover some really good packages/plugins that you should consider using to make your life and work even simpler.\nHappy coding!!!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"November 10, 2015","updated_date":null,"description":"Getting started with one of the lightweight Code Editor Sublime Text and introduction to Snippets, Project and Macros","title":"Beginner's Guide for Sublime Text 3 Plugins","tags":["SublimeText","CodeEditor"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/fe6e52be480d783d993428df72436141/7d145/Beginner-Guide-Sublime-Text.png","srcSet":"/static/fe6e52be480d783d993428df72436141/69585/Beginner-Guide-Sublime-Text.png 200w,\n/static/fe6e52be480d783d993428df72436141/497c6/Beginner-Guide-Sublime-Text.png 400w,\n/static/fe6e52be480d783d993428df72436141/7d145/Beginner-Guide-Sublime-Text.png 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Team LoginRadius","github":"LoginRadius","avatar":null}}}},{"node":{"excerpt":"In order to display your LoginRadius Login Interface in a pop-up you can leverage Jquery-ui which is a well documented, easy-to-use library…","fields":{"slug":"/engineering/displaying-the-loginradius-interface-in-a-pop-up/"},"html":"<p>In order to display your LoginRadius Login Interface in a pop-up you can leverage Jquery-ui which is a well documented, easy-to-use library that allows you to handle some common functionality such as pop-up dialogs and other UI features. In this article we go over the steps to use Jquery-ui to display a pop-up on your page with a LoginRadius login interface using the LoginRadius HTML SDK.</p>\n<p>1. Get the required references this guide relies on: Jquery and Jquery-ui. You can include the hosted reference files in the header of your page:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>2. Include the LoginRadius Interface Javascript and HTML5 SDK reference:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">options</span><span class=\"mtk1\">={};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">options</span><span class=\"mtk1\">.</span><span class=\"mtk12\">login</span><span class=\"mtk1\">=</span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">util</span><span class=\"mtk1\">.</span><span class=\"mtk11\">ready</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\"> () {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$ui</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">lr_login_settings</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">interfacesize</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">apikey</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">callback</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">lrinterfacecontainer</span><span class=\"mtk1\"> =</span><span class=\"mtk8\">&quot;interfacecontainerdiv&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">options</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>3. Create the HTML structure for your page. Below we have created a button to trigger our pop-up display as well as the dialog container that will be displayed in the custom pop-up which is hidden by default. We have also included a div to display profile data after successfully authenticating.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">Login</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> --&gt;</span></span></code></pre>\n<p>4. Create a JavaScript function to handle the display of the pop-up dialog. The below function utilizes Jquery-ui functions to display the dialog and the LoginRadius login interface initialization function to render the login interface on the popup:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Login</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;#dialog&quot;</span><span class=\"mtk1\"> ).</span><span class=\"mtk11\">dialog</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">options</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>5. Include the JavaScript callback script to handle a successful authentication and display the profile data.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">LoginRadiusSDK</span><span class=\"mtk1\">.</span><span class=\"mtk11\">setLoginCallback</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Successfullylogin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Successfullylogin</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">LoginRadiusSDK</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getUserprofile</span><span class=\"mtk1\">( </span><span class=\"mtk4\">function</span><span class=\"mtk1\">( </span><span class=\"mtk12\">data</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;#dialog&quot;</span><span class=\"mtk1\"> ).</span><span class=\"mtk11\">dialog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;close&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;profile&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk12\">innerHTML</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Full Example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">options</span><span class=\"mtk1\">={};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">options</span><span class=\"mtk1\">.</span><span class=\"mtk12\">login</span><span class=\"mtk1\">=</span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">util</span><span class=\"mtk1\">.</span><span class=\"mtk11\">ready</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\"> () {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ui</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">lr_login_settings</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">interfacesize</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">apikey</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">callback</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ui</span><span class=\"mtk1\">.</span><span class=\"mtk12\">lrinterfacecontainer</span><span class=\"mtk1\"> =</span><span class=\"mtk8\">&quot;interfacecontainerdiv&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">options</span><span class=\"mtk1\">); }); </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Login</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;#dialog&quot;</span><span class=\"mtk1\"> ).</span><span class=\"mtk11\">dialog</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">LoginRadius_SocialLogin</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">options</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">LoginRadiusSDK</span><span class=\"mtk1\">.</span><span class=\"mtk11\">setLoginCallback</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Successfullylogin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Successfullylogin</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">LoginRadiusSDK</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getUserprofile</span><span class=\"mtk1\">( </span><span class=\"mtk4\">function</span><span class=\"mtk1\">( </span><span class=\"mtk12\">data</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;#dialog&quot;</span><span class=\"mtk1\"> ).</span><span class=\"mtk11\">dialog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;close&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;profile&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk12\">innerHTML</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Login</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"November 09, 2015","updated_date":null,"description":null,"title":"Displaying the LoginRadius interface in a pop-up","tags":["HTML","Login","UI","LoginRadius Interface"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/af7b348bc73adfcd737b8df292359566/6d161/simplepop-150x150.png","srcSet":"/static/af7b348bc73adfcd737b8df292359566/6d161/simplepop-150x150.png 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"Almost every active website worldwide uses jQuery, you can check stats here , but using it without optimization might make the DOM very slow…","fields":{"slug":"/engineering/optimize-jquery-sizzle-element-selector/"},"html":"<p>Almost every active website worldwide uses jQuery, you can check stats <a href=\"http://trends.builtwith.com/javascript/jQuery\">here</a> , but using it without optimization might make the DOM very slow. The same goes for other javascript libraries, such as SizzleJS. To ensure the performance of your DOM, you have to follow some best practices for it.</p>\n<p>In this article I am going to list down some of the most critical factors that you need to watch out. Even though this not a complete list; taking care of these will help you optimize those jQuery Selector.</p>\n<h3 id=\"lets-start\" style=\"position:relative;\"><a href=\"#lets-start\" aria-label=\"lets start permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Let's start!</strong></h3>\n<h4 id=\"always-cache-your-selector\" style=\"position:relative;\"><a href=\"#always-cache-your-selector\" aria-label=\"always cache your selector permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Always cache your selector</h4>\n<p>Whenever you apply any selector in jQuery or <a href=\"http://sizzlejs.com/\">SizzleJS</a>,  the selector engine goes through the whole DOM to find the specified element.</p>\n<p>For example, if you use the code below, it will go through the whole DOM twice in order to find \".myClass\" selector.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">show</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">addClass</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;anotherClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>But instead of that, if you make all the methods in a chained format like this. It will only try to find that class once.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">show</span><span class=\"mtk1\">().</span><span class=\"mtk11\">addClass</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;anotherClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Or if you want to use this element in other places; you can do so by doing it in this way.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">myElem</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">myElem</span><span class=\"mtk1\">.</span><span class=\"mtk11\">show</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">myElem</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addClass</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;anotherCLass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>In both of these cases, the selector will be executed only once. Some selectors are very slow to traverse and passing them again and again will make your DOM very slow.</p>\n<p>Read on the next point to understand,  how the type of selector affects performance.</p>\n<h4 id=\"prioritizing-selectors-based-on-their-performance\" style=\"position:relative;\"><a href=\"#prioritizing-selectors-based-on-their-performance\" aria-label=\"prioritizing selectors based on their performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prioritizing selectors based on their performance</h4>\n<p>Selector's type affects the performance of your site. SizzleJS is a smart selector engine that also uses native js APIs for finding specific element. This is the main reason why ID selector and tag selector perform faster than others. But, if you prefer using jQuery, it’s pretty much the same. Modern browsers also have an API to find an element by class name but, let’s just focus on jQuery and SizzleJS.</p>\n<ul>\n<li>The order of selector's performance (fast -> slow) is</li>\n<li>ID selector ($(\"#ID\")) = Fastest</li>\n<li>Tag ($(\"Tag\")) = Fast</li>\n<li>Class ($(\".Class\")) = Average</li>\n<li>Attribute ($(\"[Attribute='Value']\")) = Slow</li>\n<li>Pseudo ($(\":pseudo\")) = Slower</li>\n</ul>\n<p>You can verify performance. In some exceptional cases, the selection of those tags does not matter; It’s all in the combination of the selectors. Because, it affects the performance of your site, let's discuss this on next point.</p>\n<h4 id=\"selecting-id-selector-first-and-then-other-ones\" style=\"position:relative;\"><a href=\"#selecting-id-selector-first-and-then-other-ones\" aria-label=\"selecting id selector first and then other ones permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Selecting ID selector first and then other ones</h4>\n<p>If you have the combination of selectors, then the sequence of selectors matter for optimization. For example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;#someId div .someClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>The same code can be written as:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;#someId&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">find</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;div .someClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Both of these variant represent the same thing but in the term of performance, second one is better. The reason for that is because in the first code, Sizzle will go through the DOM 3 times to find #someId, div, and .someClass.</p>\n<p>In the second one, the selector engine will go through the DOM again but, this time, it’ll only look for #someId and then find the rest inside that element without going through the DOM again.</p>\n<p>See how this will affect performance.</p>\n<h4 id=\"being-more-specific-in-right-hand-side-instead-of-left-hand-side\" style=\"position:relative;\"><a href=\"#being-more-specific-in-right-hand-side-instead-of-left-hand-side\" aria-label=\"being more specific in right hand side instead of left hand side permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Being more specific in right hand side instead of left hand side</h4>\n<p>Sizzle executes selector from right to left so it will definitely  improve performance if applied in right except left.</p>\n<p><strong>Unoptimized code:</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;div.myclass .myChildClass&quot;</span><span class=\"mtk1\"> );</span></span></code></pre>\n<p><strong>Optimized code:</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&quot;.myclass td.myChildClass&quot;</span><span class=\"mtk1\"> );</span></span></code></pre>\n<p>If you don’t see the difference, find the div and td.</p>\n<h4 id=\"selection-inside-a-parent-always-improves-performance\" style=\"position:relative;\"><a href=\"#selection-inside-a-parent-always-improves-performance\" aria-label=\"selection inside a parent always improves performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Selection inside a parent always improves performance</h4>\n<p>When you have a context, or any level of parent, then you can select an element inside that parent. It will perform better this way than selecting it directly. Because, in this case, the selector engine goes through the DOM once to find the parent.</p>\n<p>For example, assuming you are trying to find “.child” class:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.child&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Is slower than</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">parent</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;#parent&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">parent</span><span class=\"mtk1\">.</span><span class=\"mtk11\">find</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.child&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">show</span><span class=\"mtk1\">();</span></span></code></pre>\n<p>You can also specify context by following syntax</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.child&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">parent</span><span class=\"mtk1\">).</span><span class=\"mtk11\">show</span><span class=\"mtk1\">();</span></span></code></pre>\n<h4 id=\"excessive-selector-slows-down-your-query\" style=\"position:relative;\"><a href=\"#excessive-selector-slows-down-your-query\" aria-label=\"excessive selector slows down your query permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Excessive selector slows down your query</h4>\n<p>The selector engine always checks every selector you have specified and it might traverse slowly. That being said, always make sure to specify minimum selectors in order to maintain the performance.</p>\n<p>For example, you are  trying to find “.myClass” using both of these code variants,</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;#div div span.myClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Is slower than</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;#div&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">find</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<h4 id=\"\" style=\"position:relative;\"><a href=\"#\" aria-label=\" permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h4>\n<p><strong>The .children() tag is quicker than .find()</strong></p>\n<p>In case, you are trying to find a children element, it is recommended to use .children() instead of .find(). Using .find() will tell jQuery to look on every level of children, while .children() will find only the first level children. Therefore .children() is faster than .find().</p>\n<p>For example, you are trying to find “.child” inside $parent and it is the first level children of the $parent.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">parent</span><span class=\"mtk1\">.</span><span class=\"mtk11\">find</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.child&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Is slower than</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">parent</span><span class=\"mtk1\">.</span><span class=\"mtk11\">children</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.child&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">show</span><span class=\"mtk1\">();</span></span></code></pre>\n<h4 id=\"-1\" style=\"position:relative;\"><a href=\"#-1\" aria-label=\" 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h4>\n<p>Use minimum DOM append</p>\n<p>DOM manipulation is very heavy so always try to ignore or minimize using it.</p>\n<p>For example, by using the code below, it will make the process sluggish because you didn’t apply any selector caching. Resulting in going through  the DOM ten times and appending an element.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\">( </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> &lt; </span><span class=\"mtk7\">10</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\">++) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">append</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>But instead of using the above code, using the code below will solve the whole issue of appending and traversal. Not only that, it will merge the 10 times manipulation of DOM into a single call.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">myClassInnerHtml</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\">( </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> &lt; </span><span class=\"mtk7\">10</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\">++ ){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">myClassInnerHtml</span><span class=\"mtk1\"> += </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.myClass&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">append</span><span class=\"mtk1\">(</span><span class=\"mtk12\">myClassInnerHtml</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>All the tips I have mentioned above is highly dependant on your requirement but one thing is for sure; Optimization will definitely improve your process.  ‘SizzleJS’ is most the powerful and quick element selector. But, without writing optimized code you can’t prevent the DOM from freezing. With that being said,  jQuery is awesome but without optimized code it can get more DOM freezes and frustrate your users.</p>\n<p>I hope this help you optimize your element selecting. Thank you and have a great coding.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"November 05, 2015","updated_date":null,"description":null,"title":"Optimize jQuery & Sizzle Element Selector","tags":["Engineering","JQuery"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/792265a42f42bb24e4108f2d9f5488be/6d161/jquery-sizzle-element-selector-150x150.png","srcSet":"/static/792265a42f42bb24e4108f2d9f5488be/6d161/jquery-sizzle-element-selector-150x150.png 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}}]},"markdownRemark":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},"pageContext":{"limit":6,"skip":264,"currentPage":45,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}