<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[istavros]]></title><description><![CDATA[istavros]]></description><link>https://istavros.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1643239369690/V2ptq1Kwi.png</url><title>istavros</title><link>https://istavros.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 04:41:25 GMT</lastBuildDate><atom:link href="https://istavros.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to make simple slideshow using cool CSS and JS features]]></title><description><![CDATA[Hello. Today I'm making a simple slideshow using cool CSS and JS features.
I'm gonna be using:

CSS variables
CSS transformations
CSS functions 
CSS grid
JS Proxy

The HTML
<div class="slideshow">
  <div class="slides-container">
    <div class="slid...]]></description><link>https://istavros.dev/how-to-make-simple-slideshow-using-cool-css-and-js-features</link><guid isPermaLink="true">https://istavros.dev/how-to-make-simple-slideshow-using-cool-css-and-js-features</guid><category><![CDATA[javascript proxy]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[proxy]]></category><category><![CDATA[css variables]]></category><category><![CDATA[CSS Grid]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Sun, 13 Nov 2022 00:35:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668287942190/YHkgHR4ZB.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello. Today I'm making a simple slideshow using cool CSS and JS features.
I'm gonna be using:</p>
<ul>
<li>CSS variables</li>
<li>CSS transformations</li>
<li>CSS functions </li>
<li>CSS grid</li>
<li>JS Proxy</li>
</ul>
<h2 id="heading-the-html">The HTML</h2>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slideshow"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slides-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slides"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slide"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/600/300?v=1"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slide"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/600/300?v=2"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slide"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/600/300?v=3"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slide"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/600/300?v=4"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"slide"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/600/300?v=5"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bullets"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"prev"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"1.5"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-6 h-6"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M15.75 19.5L8.25 12l7.5-7.5"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"next"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"1.5"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-6 h-6"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M8.25 4.5l7.5 7.5-7.5 7.5"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Let's break it down.</p>
<p>We have a div containing the whole slideshow with a class of <code>.slideshow</code>. This container has 3 immediate children. The first is the <code>.slides-container</code> which will act as the "window" behind which our slides will be showing. Then there is an empty <code>.bullets</code> container where we will dynamically put the bullets based on the number of slides. And the last one is the <code>.buttons</code> container, with the <code>.prev</code> and <code>.next</code> buttons.</p>
<p>Inside the <code>.slides-container</code> there is another container with a class of <code>.slides</code> which holds all our slides. This div will be moving right and left behind our "window" to reveal the active slide.</p>
<p>For the images I used pictures from <a href="https://picsum.photos" target="_blank">https://picsum.photos</a>, and for the <code>.prev</code> and <code>.next</code> buttons I used some icons from <a href="https://heroicons.com" target="_blank">https://heroicons.com</a>.</p>
<h2 id="heading-the-css">The CSS</h2>
<p>First, let's define some CSS variables that we will use later.</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--max-size</span>: <span class="hljs-number">600px</span>;  
  <span class="hljs-attribute">--size</span>: <span class="hljs-built_in">min</span>(var(--max-size), <span class="hljs-number">100vw</span>);
  <span class="hljs-attribute">--active</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<p>The <code>--max-size</code> is the maximum size of each slide. 
The <code>--size</code> is the calculated size of the whole slideshow. It will be 100vw for screens smaller than <code>--max-size</code>, and <code>--max-size</code> for larger screens.
The <code>--active</code> variable holds the index of the active slide.</p>
<p>Now, the outer container will be a CSS grid with 1 column and 2 rows. The first row will contain the slides and the buttons, and the second row will contain the bullets.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.slideshow</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr auto;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--size);
}
</code></pre>
<p>Then, our "window". The <code>.slides-container</code> will sit in column 1 and row 1 of the parent grid. It will create a hole (a window), by having a transparent background and hiding anything overflowing.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.slides-container</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">overflow</span>: hidden;
}
</code></pre>
<p>Then the <code>.slides</code>. This is a div containing all our slides. It has  <code>display: flex</code> to put everything in a row, and it will move around to reveal the active slide. The interesting part here is the calculation of the container position based on the active slide and the size of the slideshow. 
It is <code>-1 * size * active</code>. Let's say the size is 600px. When the active slide is the 0th one, then it will give us 0 move on the x-axis. When the active is the 1st, then it will give <code>-1 * 600px * 1 = -600px</code> so it will move 600px to the left.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.slides</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(calc(-<span class="hljs-number">1</span> * var(--size) * <span class="hljs-built_in">var</span>(--active)));
  <span class="hljs-attribute">transition</span>: transform <span class="hljs-number">0.3s</span> ease;
}
</code></pre>
<p>Our images need to have a width equal to the <code>--size</code> variable, in order to be responsive. This is because their parent is really long and we can't rely on the image taking up all the available width and having a height of auto.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--size);
}
</code></pre>
<p>Then the buttons container. This div has to sit on top of the slides. I don't like using <code>position: absolute</code> so I used the grid feature of putting multiple elements in the same grid cell. So I put it in the same grid cell as the <code>.slides-container</code>. The problem with this is that I cannot click on the slides themselves. If the slides had a link I wouldn't be able to click on it because another div is in front of it. To tackle this problem I added <code>pointer-events: none</code> at the buttons container. Now I cannot click the buttons. So I add <code>pointer-events: all</code> at the buttons.
The buttons in this container will be in the middle vertically and at the sides horizontally. </p>
<pre><code class="lang-css"><span class="hljs-selector-class">.buttons</span> {
  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-between; <span class="hljs-comment">/* Horizontally at the sides */</span>
  <span class="hljs-attribute">align-items</span>: center; <span class="hljs-comment">/* Vertically in the middle */</span>
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">pointer-events</span>: none;
}
</code></pre>
<p>I don't think it is essential to include the buttons styling here. I have a codepen later to showcase the slideshow demo.</p>
<p>The <code>.bullets</code> container sits in row 2 of the slideshow grid. It aligns the bullets at the center.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.bullets</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">2</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">12px</span>;
}
</code></pre>
<p>Each bullet is round and the one corresponding to the active slide has different styling.</p>
<p>So far we have this. It doesn't work yet, but it's styled.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/BaVRGGb">https://codepen.io/istavros/pen/BaVRGGb</a></div>
<h2 id="heading-the-javascript">The javascript</h2>
<p>First, let's keep some useful stuff in variables.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// We keep references to all needed elements.</span>
<span class="hljs-keyword">const</span> slideshow = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".slideshow"</span>);
<span class="hljs-keyword">const</span> slidesContainer = slideshow.querySelector(<span class="hljs-string">".slides"</span>);
<span class="hljs-keyword">const</span> slides = slideshow.querySelectorAll(<span class="hljs-string">".slide"</span>);
<span class="hljs-keyword">const</span> bulletContainer = slideshow.querySelector(<span class="hljs-string">".bullets"</span>);
<span class="hljs-keyword">const</span> prev = slideshow.querySelector(<span class="hljs-string">".prev"</span>);
<span class="hljs-keyword">const</span> next = slideshow.querySelector(<span class="hljs-string">".next"</span>);
<span class="hljs-keyword">const</span> length = slides.length;
</code></pre>
<p>Then, let's create the bullets based on the slide count. I use documentFragmet here to insert new elements into the DOM.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Automatically create the bullets based on</span>
<span class="hljs-comment">// the amount of slides we have.</span>
<span class="hljs-keyword">const</span> fragment = <span class="hljs-built_in">document</span>.createDocumentFragment();
slides.forEach(<span class="hljs-function">(<span class="hljs-params">slide, index</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> bullet = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"span"</span>);
  bullet.classList.add(<span class="hljs-string">"bullet"</span>);
  <span class="hljs-keyword">if</span> (!index) {
    <span class="hljs-comment">// Set the first bullet as active</span>
    bullet.classList.add(<span class="hljs-string">"active"</span>);
  }
  <span class="hljs-comment">// Add the click functionality to the bullet</span>
  bullet.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> active.slide = index);
  fragment.appendChild(bullet);
});
bulletContainer.appendChild(fragment);

<span class="hljs-comment">// Keep a reference to the bullets</span>
<span class="hljs-comment">// so we can add/remove the .active class.</span>
<span class="hljs-keyword">const</span> bullets = bulletContainer.querySelectorAll(<span class="hljs-string">".bullet"</span>);
</code></pre>
<p>Now let's add functionality to the buttons. When clicking on the <code>.next</code> button we want to increase the <code>active</code> index by 1, and when clicking on the <code>.prev</code> button we want to decrease the <code>active</code> index by 1.
When we reach the last slide and click next, it should go back to the first. And when we are at the first and click previous it should go to the last one. However, I don't really like to put this logic into the click handlers, because by clicking <code>.next</code> I don't care which one is the next one. Just show me the next. So I used the magic of JavaScript Proxy. You may have noticed that in the bullet click listener I used <code>active.slide</code> to set the active slide index. Here is how it goes.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// We use Proxy to include some kind of reactivity.</span>
<span class="hljs-comment">// By just changing active.slide, the DOM gets</span>
<span class="hljs-comment">// changed automatically, without the need to</span>
<span class="hljs-comment">// make the DOM changes within the event handlers.</span>
<span class="hljs-keyword">const</span> active = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(
  { <span class="hljs-attr">slide</span>: <span class="hljs-number">0</span> },
  {
    set(obj, prop, value) {
      <span class="hljs-keyword">if</span> (prop == <span class="hljs-string">"slide"</span>) {
        <span class="hljs-comment">// If we click "prev" while on the first slide</span>
        <span class="hljs-comment">// then go to the last one.</span>
        <span class="hljs-keyword">if</span> (value &lt; <span class="hljs-number">0</span>) {
          value = length - <span class="hljs-number">1</span>;
        }

        <span class="hljs-comment">// If we click "next" while on the last slide</span>
        <span class="hljs-comment">// then go to the first one.</span>
        <span class="hljs-keyword">if</span> (value &gt;= length) {
          value = <span class="hljs-number">0</span>;
        }

        <span class="hljs-comment">// Make the appropriate DOM changes</span>
        slidesContainer.style.setProperty(<span class="hljs-string">"--slide"</span>, value);
        bullets[obj[prop]].classList.remove(<span class="hljs-string">"active"</span>);
        bullets[value].classList.add(<span class="hljs-string">"active"</span>);
      }

      <span class="hljs-comment">// Actually set the active.slide prop to it's new value</span>
      obj[prop] = value;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
  }
);
</code></pre>
<p>As stated in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#description">MDN</a> website</p>
<blockquote>
<p>The Proxy object allows you to create an object that can be used in place of the original object, but which may redefine fundamental Object operations like getting, setting, and defining properties.</p>
</blockquote>
<p>I give the Proxy a target object as the first argument, and a handler as the second argument. Into the handler there is a setter function.
The first argument <code>obj</code> is the target object <code>{ slide: 0 }</code>. The second argument <code>prop</code> is the property we are setting, in our case <code>slide</code>. And the third argument is the value we are setting to the property.
Into the setter is where I put all the logic for calculating which slide is the one that should be showing, and making the appropriate DOM changes. We can see that the only DOM change that has to be done is to set the <code>--active</code> CSS variable the the appropriate active slide index, and to toggle the <code>.active</code> class on the corresponding bullet.</p>
<p>With the help of the JavaScript Proxy, I am able to separate concerns and add very simple click handlers at the <code>.prev</code> and <code>.next</code> buttons.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Add the prev/next functionality to the buttons</span>
prev.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> active.slide--);
next.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> active.slide++);
</code></pre>
<p>Here is the completed codepen.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/JjZGBpY">https://codepen.io/istavros/pen/JjZGBpY</a></div>
<p>And finally here is another codepen. It's the same as the last one, but if you press space, it goes 3D to show how the elements are placed on top of each other, and how the "window" works.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/QWxvJwJ">https://codepen.io/istavros/pen/QWxvJwJ</a></div>
<p>I hope you liked the techniques I used to make this slideshow. I would love to hear better alternatives. I'm always up for learning something new.</p>
<p>Thanks for reading this far!</p>
]]></content:encoded></item><item><title><![CDATA[How to create a brand logo grid]]></title><description><![CDATA[In this post I will demonstrate how to create a brand logo grid like the one below:

The tricky part of such a grid is the colored gap between the logo tiles.
The solution I came up with, I think is acceptable.
I added a 1px box-shadow to the grid it...]]></description><link>https://istavros.dev/how-to-create-a-brand-logo-grid</link><guid isPermaLink="true">https://istavros.dev/how-to-create-a-brand-logo-grid</guid><category><![CDATA[CSS grid gap]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS Grid]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Sun, 30 Oct 2022 20:33:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666915425722/Q7gXi507H.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post I will demonstrate how to create a brand logo grid like the one below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666914811665/cwtLIkb6v.png" alt="Screenshot 2022-10-28 at 02.25.36.png" /></p>
<p>The tricky part of such a grid is the colored gap between the logo tiles.</p>
<p>The solution I came up with, I think is acceptable.
I added a 1px box-shadow to the grid items, and I used the wrapper’s :after element to hide the "border" around the grid</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.brand-grid</span> {
  <span class="hljs-attribute">flex-grow</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(auto-fill, minmax(<span class="hljs-number">230px</span>, <span class="hljs-number">1</span>fr));

  // this is the empty space where the lines will go
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">1px</span>;

  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">position</span>: relative;

  &amp;:after {
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">position</span>: absolute;
    // Remove pointer events because
    // this element covers everything.
    <span class="hljs-attribute">pointer-events</span>: none;

    // By using negative inset value
    // we make <span class="hljs-attribute">the </span>:after pseudo-element
    // <span class="hljs-number">2px</span> larger than its parent.
    // This is because the lines that we want to hide,
    // overflow the container because they are shadows.
    inset: -<span class="hljs-number">2px</span>;

    // this 3px box shadow will hide 
    // the overflown lines, and 1 more px.
    <span class="hljs-attribute">box-shadow</span>: inset <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">#fff</span>;
  }

}

<span class="hljs-selector-class">.item</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">1px</span> <span class="hljs-number">#ddd</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/JjZoeXW">https://codepen.io/istavros/pen/JjZoeXW</a></div>
]]></content:encoded></item><item><title><![CDATA[Two ways to handle ltr/rtl on a page.]]></title><description><![CDATA[When creating a multilingual web page you might need to handle languages written from right to left. This comes with some design issues.
First, you must add the dir attribute to your root (<html>) element. But the dir attribute alone cannot tackle ev...]]></description><link>https://istavros.dev/two-ways-to-handle-ltrrtl-on-a-page</link><guid isPermaLink="true">https://istavros.dev/two-ways-to-handle-ltrrtl-on-a-page</guid><category><![CDATA[ltr]]></category><category><![CDATA[rtl]]></category><category><![CDATA[right-to-left]]></category><category><![CDATA[CSS]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Fri, 21 Oct 2022 20:23:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/lPQIndZz8Mo/upload/v1666381558069/Xn7JAM912.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When creating a multilingual web page you might need to handle languages written from right to left. This comes with some design issues.</p>
<p>First, you must add the <code>dir</code> attribute to your root (<code>&lt;html&gt;</code>) element. But the <code>dir</code> attribute alone cannot tackle everything. Sometimes you might have an image next to a paragraph, and a <code>margin-left</code> spacing them out. When you switch to the rtl language, you end up with a paragraph with a left margin, and an image stuck on the right side of it.</p>
<p>I will show you two ways that I have used to solve this problem.</p>
<h2 id="heading-using-css-variables">Using CSS variables</h2>
<p>The first way I thought was using CSS variables and some calculations to play with the left margin.</p>
<pre><code>html[dir=<span class="hljs-string">"ltr"</span>] {
  --ltr: <span class="hljs-number">1</span>;
  --rtl: <span class="hljs-number">0</span>;
}

html[dir=<span class="hljs-string">"rtl"</span>] {
  --ltr: <span class="hljs-number">0</span>;
  --rtl: <span class="hljs-number">1</span>;
}

p {
  margin-left: calc(<span class="hljs-keyword">var</span>(--ltr) * <span class="hljs-number">20</span>px);
  margin-right: calc(<span class="hljs-keyword">var</span>(--rtl) * <span class="hljs-number">20</span>px);
}
</code></pre><p>What I do here is assign a number (0, 1) to the "boolean" variables <code>--ltr</code> and <code>--rtl</code>, declaring which direction is enabled. When the <code>dir</code> changes, the variables swap values. Then I calculate the left and right margins by multiplying the variables with the desired pixel value. So in ltr the left margin will be <code>1 × 20px = 20px</code>, and the right margin will be <code>0 × 20px = 0</code>. When we change to rtl the margins will swap values.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/zYjgPQe">https://codepen.io/istavros/pen/zYjgPQe</a></div>
<h2 id="heading-using-modern-css">Using modern CSS</h2>
<p>This is a clever way of setting the margins based on a boolean enabled/disabled variable. But, there is a better way by using modern CSS.</p>
<pre><code>p {
  margin-inline-start: <span class="hljs-number">20</span>px;
}
</code></pre><p>And that's it. Way less code, and more elegant. It actually instructs the browser to add a 20px margin at the "start" of the x-axis. The start of the x-axis is relative to the direction set by the <code>dir</code> attribute. So in this case the browser will set a 20px left margin on ltr direction, and a 20px right margin on rtl direction.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/OJZKQOq">https://codepen.io/istavros/pen/OJZKQOq</a></div>
]]></content:encoded></item><item><title><![CDATA[Work needs meaning]]></title><description><![CDATA[Hello again. In this post, I'm going to share a thought I had.
For the last six months, I've been struggling with not-so-interesting work. It was some things that I had to do that were so boring I almost believed that I didn't like my job anymore. I ...]]></description><link>https://istavros.dev/work-needs-meaning</link><guid isPermaLink="true">https://istavros.dev/work-needs-meaning</guid><category><![CDATA[ownership]]></category><category><![CDATA[creativity]]></category><category><![CDATA[meaning]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Fri, 14 Oct 2022 22:23:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665786558552/OlZ1geMgI.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello again. In this post, I'm going to share a thought I had.</p>
<p>For the last six months, I've been struggling with not-so-interesting work. It was some things that I had to do that were so boring I almost believed that I didn't like my job anymore. I was in a downward spiral of thoughts about quitting and trying to follow a different career. My spirit had died as I had lost every drop of creativity that programming usually has.</p>
<p>In all that I had some people telling me that if I don’t enjoy what I do then it’s time to move on and do something else. Easier said than done though when you have a family depending on you.</p>
<p>So I started listening to podcasts and watching YouTube videos about productivity, happiness, and well-being.</p>
<p>I got from this that people need some kind of meaning, ownership, and creativity in their work, to enjoy It and feel fulfilled.</p>
<p>After every YouTube video or podcast episode I watched or listened to, I felt motivated to continue the hard work and finish my assignments.</p>
<p>Inspired by these people I decided that I had to “create” meaning, ownership, and creativity in every task I had to do, to sustain my mental peace. So I started adding small touches of creative work within the boring stuff. And this kept me going for six months.</p>
<p>Although this tactic was helping, I was still feeling that I didn’t like this job anymore.</p>
<p>This was until I sat my ass down for a weekend and remade an old application that we use in the company. This time I used newer, better, and more exciting technologies. It was as if a light came upon me. I started enjoying coding again. I found my lost creativity, my inner peace. I will not get paid extra for the work I put in on the weekend, but I enjoyed every second of it and this is what matters most.</p>
<p>When I showed the remade application to my boss and colleagues, they all liked it a lot. They also said that they could see that I made it with love and attention to detail. From now on we will be using this new version of the application that I made.</p>
<p>I found meaning in this because it’s an essential application for the company’s goals.</p>
<p>I felt I owned the application because I created everything myself and made the necessary decisions.
I felt I had ownership of the application because it is I who will continue supporting and developing it.</p>
<p>I found creativity in every decision I made and thought about how it should work.</p>
<p>Sometimes we have to do boring tasks in life (or work). Yet, we should try to find, or create, some interest within the tasks. When I had to code a boring redesign I tried hard to come up with something interesting to add to it. I ended up creating the interactive gradient scrollbar that I wrote about in a <a target="_blank" href="https://istavros.dev/create-an-interactive-gradient-scrollbar">previous post</a>. This was the little touch of creativity that I needed to get me going and finish the task.</p>
<p>Thank you, and have a great day!</p>
]]></content:encoded></item><item><title><![CDATA[How to choose between grid and flex for a listing page]]></title><description><![CDATA[When we need to show a list of items, such as products in a product list page, we have the following two css alternatives:

display: grid
display: flex

I will demonstrate both here and I will explain why I choose one over the other.
Usually, we have...]]></description><link>https://istavros.dev/how-to-choose-between-grid-and-flex-for-a-listing-page</link><guid isPermaLink="true">https://istavros.dev/how-to-choose-between-grid-and-flex-for-a-listing-page</guid><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[flexbox]]></category><category><![CDATA[Flex]]></category><category><![CDATA[CSS Grid]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Fri, 22 Jul 2022 16:06:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658507155422/-CXVP8D_l.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When we need to show a list of items, such as products in a product list page, we have the following two css alternatives:</p>
<ul>
<li><code>display: grid</code></li>
<li><code>display: flex</code></li>
</ul>
<p>I will demonstrate both here and I will explain why I choose one over the other.</p>
<p>Usually, we have a container around our content that limits its width to a maximum to keep it readable on large screens. In the demonstrations below I will use a container with a max-width of 400px and an Item width of 100px with a 10px gap between items. This means each row will fit 3 items (3x100px + 2x10px = 320px), and 80px will remain empty. We also need the items to be centered within the container.</p>
<h2 id="heading-using-flex">Using flex</h2>
<p>When using flex to create a grid-like structure we have to use flex-wrap. We make sure that the dimensions of our items are ok using flex-shink and flex-grow if needed. We need items to be centered so we will use <code>justify-content: center</code>. Here is a demo:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-wrap</span>: wrap;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/JjLJNjj">https://codepen.io/istavros/pen/JjLJNjj</a></div>
<p>We can see a problem here. The last row is not complete and the items are centered within this row. This doesn’t look like items in a grid. If we change to <code>justify-content: flex-start</code> everything will be on the left side, and all the available free space will be on the right. Not pretty.</p>
<h2 id="heading-using-grid">Using grid</h2>
<p>By using grid we don’t need to define something like flex-wrap but we need to define the columns' widths. In our example, we know that each item needs to be 100px wide, and the number of columns should vary depending on the width of the container. To achieve this we will use the repeat function with the auto-fill value. To center the items in the container we will use again <code>justify-content: center</code>.</p>
<p>Here is the demo:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(auto-fill, <span class="hljs-number">100px</span>);
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/YzaQVrV">https://codepen.io/istavros/pen/YzaQVrV</a></div>
<p>The difference here is that although we used <code>justify-content: center</code> the last row is left aligned and the items are kept within the grid lines. This is much better than flex for this case.</p>
<p>A grid with <code>justify-content: center</code> centers the whole grid, while a flex container with <code>justify-content: center</code> centers the individual items.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With our demonstrations here we showed that when you’re making a listing page it’s better to use <code>display: grid</code> rather than <code>display: flex</code>. Flex has its advantages in different use cases.</p>
<p>If you enjoyed this post, please share.</p>
]]></content:encoded></item><item><title><![CDATA[How to create an interactive gradient scrollbar]]></title><description><![CDATA[I was recently working on implementing a new design for a project. The site branding had two main colors, and, even though it was not in the design, I thought I would change the scrollbar background to the primary branding color.
It was better than t...]]></description><link>https://istavros.dev/create-an-interactive-gradient-scrollbar</link><guid isPermaLink="true">https://istavros.dev/create-an-interactive-gradient-scrollbar</guid><category><![CDATA[CSS]]></category><category><![CDATA[scroll]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Thu, 21 Jul 2022 08:06:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658391010431/J7aUpSggc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was recently working on implementing a new design for a project. The site branding had two main colors, and, even though it was not in the design, I thought I would change the scrollbar background to the primary branding color.</p>
<p>It was better than the default browser scrollbar, but I had the idea to make it even better. So I decided to make a gradient scrollbar using the two branding colors. But having the scroll thumb with this gradient background wasn’t enough either… so I decided to make it more interactive.</p>
<p>My Idea was as you scroll, the scroll thumb background should change, starting from the primary and ending with the secondary branding colors.</p>
<p>This is how I did it. This works only on WebKit browsers of course.</p>
<p>First lets see the default scrollbar</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/ExEmXRL">https://codepen.io/istavros/pen/ExEmXRL</a></div>
<p>I changed from that to only having a solid color scroll thumb</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary</span>: <span class="hljs-number">#007ac3</span>;
  <span class="hljs-attribute">--secondary</span>: <span class="hljs-number">#d2232a</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">13px</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-thumb</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">var</span>(--primary);
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid <span class="hljs-number">#fff</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/KKomqea?editors=0100">https://codepen.io/istavros/pen/KKomqea?editors=0100</a></div>
<p>Next step is to make the gradient. I set the gradient background to the scroll track.</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary</span>: <span class="hljs-number">#007ac3</span>;
  <span class="hljs-attribute">--secondary</span>: <span class="hljs-number">#d2232a</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">13px</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-track</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(
    to bottom, 
    var(--primary), 
    <span class="hljs-built_in">var</span>(--secondary)
  );
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/bGvWRmp?editors=0100">https://codepen.io/istavros/pen/bGvWRmp?editors=0100</a></div>
<p>Then I tried to create a scroll thumb with a “hole” to reveal the gradient background.</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary</span>: <span class="hljs-number">#007ac3</span>;
  <span class="hljs-attribute">--secondary</span>: <span class="hljs-number">#d2232a</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">13px</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-track</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(
    to bottom, 
    var(--primary), 
    <span class="hljs-built_in">var</span>(--secondary)
  );
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-thumb</span> {
  <span class="hljs-attribute">background-color</span>: transparent;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid <span class="hljs-number">#fff</span>;
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/PoRmjXq?editors=1100">https://codepen.io/istavros/pen/PoRmjXq?editors=1100</a></div>
<p>And now the only thing missing is to hide the rest of the scroll track. I used a really large outline on the scroll thumb for that.</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary</span>: <span class="hljs-number">#007ac3</span>;
  <span class="hljs-attribute">--secondary</span>: <span class="hljs-number">#d2232a</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">13px</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-track</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(
    to bottom, 
    var(--primary), 
    <span class="hljs-built_in">var</span>(--secondary)
  );
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-pseudo">::-webkit-scrollbar-thumb</span> {
  <span class="hljs-attribute">background-color</span>: transparent;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">outline</span>: <span class="hljs-number">99999px</span> solid <span class="hljs-number">#fff</span>;
}
</code></pre>
<p>And this is the final result</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/istavros/pen/oNqWeLK?editors=1100">https://codepen.io/istavros/pen/oNqWeLK?editors=1100</a></div>
<p>If you liked this small tip, share it with your friends…</p>
]]></content:encoded></item><item><title><![CDATA[Messing with the global user in Drupal 7]]></title><description><![CDATA[There are times when you need to run some code as a specific user. You might want to send an email and the content is subject to the receiving users’ permissions on the site. Sometimes you might need to run some code as user 1 and not the logged-in u...]]></description><link>https://istavros.dev/messing-with-the-global-user-in-drupal-7</link><guid isPermaLink="true">https://istavros.dev/messing-with-the-global-user-in-drupal-7</guid><category><![CDATA[Drupal]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Security]]></category><category><![CDATA[securityawareness]]></category><dc:creator><![CDATA[Stavros Ioannidis]]></dc:creator><pubDate>Sat, 15 Apr 2017 19:49:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643316973521/DLWCE1ynt.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are times when you need to run some code as a specific user. You might want to send an email and the content is subject to the receiving users’ permissions on the site. Sometimes you might need to run some code as user 1 and not the logged-in user.</p>
<p>In situations like these, you need to change the global user to the user you want to impersonate.</p>
<p>It’s not that difficult to do so. Here is an example.</p>
<pre><code><span class="hljs-keyword">global</span> $user;  
$user = user_load(<span class="hljs-number">1</span>);

<span class="hljs-comment">// your code here.</span>
</code></pre><p>This example is soooo wrong. Ok, you change the global user object to user 1 so now the logged-in user has super admin access to your site…</p>
<p>A better example is the following</p>
<pre><code><span class="hljs-keyword">global</span> $user;  
$old\_user = <span class="hljs-keyword">clone</span> $user;  
$user = user_load(<span class="hljs-number">1</span>);

<span class="hljs-comment">// your code here.</span>

$user = $old_user;
</code></pre><p>Ok, that’s better. We change the user to user 1, we do what we have to do, and then we reassign the old user to the global user object. Everything is back to where it was supposed to be and we are all happy.</p>
<p>But we are humans and we make mistakes. And if these mistakes are made in our code we might end up with exceptions thrown. So let’s take a more careful look at the example above. We have cloned the logged-in user object and kept it in a variable. Then we assigned user 1 to the global user. Then we run my code and finally, we reassigned the cloned user object to the global one. Oh, wait… what if our code running as user 1 throws an exception. The global user will not be reassigned the right value and we are stuck with a user logged in as user 1! THAT IS BAD! If the user realizes what’s happening they might just hack the hell out of our site with our permission.</p>
<p>So let's refactor the example a bit to make it “immune” to exceptions.</p>
<pre><code><span class="hljs-keyword">global</span> $user;  
$old\_user = <span class="hljs-keyword">clone</span> $user;

<span class="hljs-keyword">try</span> {  
  $user = user\_load(<span class="hljs-number">1</span>);  
  <span class="hljs-comment">// your code here.</span>

}

<span class="hljs-keyword">finally</span> {  
  $user = $old\_user;  
}
</code></pre><p>Phew… now it looks ok. We wrapped our code in a try-finally block so even if our code throws an exception it will return the global user to the right one in the ‘finally’ part.</p>
<p>But there is another vulnerability here. Did you find it?</p>
<p>Me neither. A user of the site may find it though.</p>
<p>It doesn’t have to do exactly with impersonating a user. In some parts of your code, you may need to print information for a specific user. For example, we had a blog and we want to print the name of a post author with a link to a page with this author’s posts. So we go about it like this…</p>
<pre><code>$user <span class="hljs-operator">=</span> user_load(<span class="hljs-operator">&lt;</span>user_id<span class="hljs-operator">&gt;</span>);  
print $user<span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>name;
</code></pre><p>Cool, we printed the name of our user on the blog post page. But what if within the same scope someone (or maybe us) had used the global user the same way we used in the examples above</p>
<pre><code><span class="hljs-keyword">global</span> $user;
</code></pre><p>We wanted to just print a user’s name but we also changed the global user to the user who authored the blog post. What if user 1 had authored this blog post. Now anyone reading this post would have ‘root’ access to our site. THIS IS BAD!</p>
<p>The solution to this problem for me is to use <code>$GLOBALS['user']</code> instead of <code>global $user;</code> whenever we want to use the global user in any way.</p>
<p>If we want to make it even more robust we should disable saving session data whenever we change the global user like so</p>
<pre><code>$old_user = <span class="hljs-keyword">clone</span> $GLOBALS[<span class="hljs-string">'user'</span>];  
$old_session = drupal_save_session();

<span class="hljs-keyword">try</span> {  
  drupal_save_session(<span class="hljs-literal">FALSE</span>);  
  $GLOBALS[<span class="hljs-string">'user'</span>] = user_load(<span class="hljs-number">1</span>);  
  <span class="hljs-comment">// our code  </span>
}  
<span class="hljs-keyword">finally</span> {  
  $GLOBALS[<span class="hljs-string">'user'</span>] = $old_user;  
  drupal_save_session($old_session);  
}
</code></pre><p>Nice, now we can be sure that the global user will not be affected by whatever we do in there.</p>
<p>But it’s too much code to write every time we need to impersonate a user. Let's make it a function.</p>
<pre><code><span class="hljs-meta">&lt;?php</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run_as_user</span>(<span class="hljs-params">$tmp_user, $function</span>) </span>{
  <span class="hljs-keyword">if</span> (!is_callable($function)) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">FALSE</span>;
  }
  $args = func_get_args();
  array_shift($args); <span class="hljs-comment">// remove $tmp_user</span>
  array_shift($args); <span class="hljs-comment">// remove $function </span>

  $old_user = <span class="hljs-keyword">clone</span> $GLOBALS[<span class="hljs-string">'user'</span>];
  $old_session = drupal_save_session();
  <span class="hljs-keyword">try</span> {
    drupal_save_session(<span class="hljs-literal">FALSE</span>);
    $GLOBALS[<span class="hljs-string">'user'</span>] = $tmp_user;
    <span class="hljs-keyword">return</span> call_user_func_array($function, $args);
  }
  <span class="hljs-keyword">finally</span> {
    $GLOBALS[<span class="hljs-string">'user'</span>] = $old_user;
    drupal_save_session($old_session);
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">FALSE</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run_as_user_by_id</span>(<span class="hljs-params">$uid, $function</span>) </span>{
  <span class="hljs-keyword">if</span> ($tmp_user = user_load($uid)) {
    $args = func_get_args();
    $args[<span class="hljs-number">0</span>] = $tmp_user;
    <span class="hljs-keyword">return</span> call_user_func_array(<span class="hljs-string">'run_as_user'</span>, $args);
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">FALSE</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run_as_user_by_mail</span>(<span class="hljs-params">$email, $function</span>) </span>{
  <span class="hljs-keyword">if</span> ($tmp_user = user_load_by_mail($email)) {
    $args = func_get_args();
    $args[<span class="hljs-number">0</span>] = $tmp_user;
    <span class="hljs-keyword">return</span> call_user_func_array(<span class="hljs-string">'run_as_user'</span>, $args);
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">FALSE</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run_as_user_by_name</span>(<span class="hljs-params">$name, $function</span>) </span>{
  <span class="hljs-keyword">if</span> ($tmp_user = user_load_by_name($name)) {
    $args = func_get_args();
    $args[<span class="hljs-number">0</span>] = $tmp_user;
    <span class="hljs-keyword">return</span> call_user_func_array(<span class="hljs-string">'run_as_user'</span>, $args);
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">FALSE</span>;
}

<span class="hljs-comment">// EXAMPLE</span>
run_as_user_by_id(<span class="hljs-number">1</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// code to execute as user 1</span>
});
</code></pre><p>Some things are happening here.</p>
<p>First, we create the function <code>run_as_user</code> which takes a user object and a callable as arguments. Any extra arguments will be passed to the callable as its arguments (using <code>call_user_func_array</code>).</p>
<p>Then we create three utility functions so that we can impersonate a user by id, email, and name.</p>
<p>At the end, we can see a usage example.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Messing with the global user might be very dangerous on a drupal site. It could make an anonymous user super administrator. My suggestion is not to use <code>global $user</code> syntax as someone might use the user variable for other stuff. Instead, we should use the <code>$GLOBALS['user']</code> to refer to the global user object. I also gave a code snippet I use for safe user impersonation within my projects.</p>
<p>Do you think my code is not safe enough, or just stupid? Write a comment to put me in my place.</p>
]]></content:encoded></item></channel></rss>