<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fidel Leal</title>
    <description>The latest articles on DEV Community by Fidel Leal (@fleal).</description>
    <link>https://dev.to/fleal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1117943%2F1d1c03b4-0730-4324-b1de-ea5694e0f78d.png</url>
      <title>DEV Community: Fidel Leal</title>
      <link>https://dev.to/fleal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fleal"/>
    <language>en</language>
    <item>
      <title>Customizing Requests With The HTTP Gem</title>
      <dc:creator>Fidel Leal</dc:creator>
      <pubDate>Tue, 08 Aug 2023 17:53:13 +0000</pubDate>
      <link>https://dev.to/fleal/customizing-requests-with-the-http-gem-2jfn</link>
      <guid>https://dev.to/fleal/customizing-requests-with-the-http-gem-2jfn</guid>
      <description>&lt;h6&gt;
  
  
  Many APIs require requests to be formatted according to specific requirements. Beyond authentication tokens, it is often necessary to include custom headers that provide additional information to an API. The HTTP gem in Ruby provides several methods that allow us to tailor our requests.
&lt;/h6&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;For instance, the &lt;code&gt;authorization()&lt;/code&gt; method sets the header of the same name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Bearer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;YOUR_ACCESS_TOKEN_HERE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;To inform the server of the expected format for the response's content, we can set the &lt;code&gt;Accept&lt;/code&gt; header using the method with the same name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://yoururl.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Defining custom headers is also straightforward, thanks to the &lt;code&gt;headers()&lt;/code&gt; method. For example, Notion requires version information to be sent along with requests to its API. It is possible to include that header as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Notion-Version"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"2022-06-28"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.notion.com/v1/databases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We can even chain all these methods together in our request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Bearer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;YOUR_ACCESS_TOKEN_HERE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Notion-Version"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"2022-06-28"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.notion.com/v1/databases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In order to maintain code organization and readability, we could choose to stick to a single method and just pass a hash to &lt;code&gt;headers()&lt;/code&gt;, as opposed to chaining multiple methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;my_headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Authorization"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Bearer YOUR_ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"Notion-Version"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"2022-06-28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"Accept"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"Your-Custom-Header"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"custom-header-value"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.notion.com/v1/databases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In summary, the HTTP gem offers great flexibility to customize our requests, accommodating the needs of various APIs and facilitating more effective communication with different web services.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using Sinatra Filters</title>
      <dc:creator>Fidel Leal</dc:creator>
      <pubDate>Mon, 07 Aug 2023 17:29:52 +0000</pubDate>
      <link>https://dev.to/fleal/using-sinatra-filters-2a77</link>
      <guid>https://dev.to/fleal/using-sinatra-filters-2a77</guid>
      <description>&lt;h6&gt;
  
  
  Sinatra filters are special methods invoked for each individual request and evaluated in the same context as the routes. They provide an efficient way to organize logic and make variables available across multiple routes. There are two types of filters, &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt;, named for when they are executed in relation to a particular request.
&lt;/h6&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;before&lt;/code&gt; filter's use cases include authentication, logging, and the declaration of instance variables that should be available to all or a several routes &lt;strong&gt;within the same request-response cycle&lt;/strong&gt;. This is an important distinction! Variables declared inside a &lt;code&gt;before&lt;/code&gt; filter will be initialized before each request and made available to all the routes that follow in that particular cycle. This behavior is different from regular instance variables declared in the body of the application, which can retain their value across different requests.&lt;/p&gt;

&lt;p&gt;Here is a hypothetical example, showcasing the use of &lt;code&gt;before&lt;/code&gt; in a version of the Umbrella app that implements user authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="c1"&gt;# Redirect to login route if user not authenticated&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
        &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/login'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;  

    &lt;span class="c1"&gt;# Log the request &lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="s2"&gt;"Request: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request_method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Params: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Pre-process some data from the request to make it available to the routes&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
        &lt;span class="vi"&gt;@user_coordinates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_coordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"user_location"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Helper method to retrieve user's location coordinates from Google Maps' API&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;get_coordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="c1"&gt;# Make a request to Google Map's API and process response to get the specific coordinates&lt;/span&gt;
    &lt;span class="n"&gt;user_coordinates&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;after&lt;/code&gt; filter has access to a similar context as &lt;code&gt;before&lt;/code&gt;. However, as its name implies, it is invoked &lt;em&gt;after&lt;/em&gt; the route block is finished. (Although I have not had the opportunity to use this filter within my applications, I am including the example below for documentation purposes.) Here is another hypothetical example. The filter is used to ensure that the response's &lt;code&gt;Content-Type&lt;/code&gt; header is appropriately set to &lt;code&gt;application/json&lt;/code&gt; before sending it back to the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/route'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="ss"&gt;message:  &lt;/span&gt;&lt;span class="s1"&gt;'This is an endpoint!'&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/another_route'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="ss"&gt;data:  &lt;/span&gt;&lt;span class="s1"&gt;'This is another endpoint!'&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'application/json'&lt;/span&gt;  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Lastly, a couple interesting aspects about filters:&lt;/p&gt;

&lt;p&gt;1) Multiple &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; filters can be defined in the same application. They can be placed before or after the routes they affect, but &lt;strong&gt;the order in which they are defined determines the order in which they will be executed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;2) Sinatra filters (like routes) can optionally accept patterns and conditions. In those cases, filters will be evaluated only when the request's path matches the specified pattern. Here is an example from Sinatra's &lt;a href="https://rubydoc.info/gems/sinatra#filters"&gt;documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Any request whose path begins with '/protected/' will require authentication&lt;/span&gt;
&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="s1"&gt;'/protected/*'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;authenticate!&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Hiding HTML elements</title>
      <dc:creator>Fidel Leal</dc:creator>
      <pubDate>Fri, 21 Jul 2023 17:00:15 +0000</pubDate>
      <link>https://dev.to/fleal/hiding-html-elements-2fn1</link>
      <guid>https://dev.to/fleal/hiding-html-elements-2fn1</guid>
      <description>&lt;h6&gt;
  
  
  After reviewing Codecademy's CSS courses, I found myself pondering the differences between &lt;code&gt;display: none&lt;/code&gt;, &lt;code&gt;visibility: hidden&lt;/code&gt;, and &lt;code&gt;visibility: collapse&lt;/code&gt;. Here is what I discovered.
&lt;/h6&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The use of &lt;code&gt;display: none&lt;/code&gt; is pretty straightforward. When applied to an element, the browser does not render it. The space in the layout becomes available and all items on the page will behave as if the hidden element did not exist.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;code&gt;visibility: hidden&lt;/code&gt; turns off the display of an element while allowing it to keep occupying its space. Thus, the remaining items will still respect the hidden element's space in the page's layout.&lt;/p&gt;

&lt;p&gt;Then there is &lt;code&gt;visibility: collapse&lt;/code&gt;, which is a little more interesting. For most elements, this declaration works in the same way as &lt;code&gt;display: none&lt;/code&gt;. The item will disappear and its space in the layout made available for other elements to occupy. However, with table and flex elements, the behavior depends on the browser we use.&lt;/p&gt;

&lt;p&gt;Table elements with &lt;code&gt;collapse&lt;/code&gt; will disappear from the page. Chrome and Firefox will remove the space occupied by the element as they do with &lt;code&gt;display: none&lt;/code&gt;, but with one important caveat:  surrounding rows and columns will maintain the exact cell dimension they had when the collapsed element was present. So, you can virtually eliminate a cell or column (and the space it occupies) &lt;em&gt;without having the table automatically adjust its dimensions&lt;/em&gt;. Unless you are using Safari, which does not seem to treat &lt;code&gt;collapse&lt;/code&gt; any differently from &lt;code&gt;hidden&lt;/code&gt; 👎👎👎.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcayc5ljq8reazlg8fep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcayc5ljq8reazlg8fep.png" alt="A nice table"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;A nice table.&lt;/b&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgwum1yscckfhvdv7hbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgwum1yscckfhvdv7hbo.png" alt="display:none applied"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;display: none&lt;/code&gt; applied. Notice how cells automatically adjust their size.&lt;/b&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz0art79s7yg67x93f2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz0art79s7yg67x93f2h.png" alt="visibility:hidden applied"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;visibility: hidden&lt;/code&gt; applied. Space is preserved and cells maintain their size.&lt;/b&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2epj8qlrui352ghdbfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2epj8qlrui352ghdbfa.png" alt="visibility:collapse applied"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;visibility: collapse&lt;/code&gt; applied. Space is removed and cells maintain their size.&lt;/b&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs7croqqhisoy999aum2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs7croqqhisoy999aum2.png" alt="visibility:hidden in Safari"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;visibility: hidden&lt;/code&gt; in Safari.&lt;/b&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1zdxgtt5ygmdnszetem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1zdxgtt5ygmdnszetem.png" alt="visibility:collapse in Safari"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;visibility: collapse&lt;/code&gt; in Safari.&lt;/b&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In the case of flex elements, most browsers will not differentiate between &lt;code&gt;collapse&lt;/code&gt; and &lt;code&gt;hidden&lt;/code&gt;. The one exception is Firefox. A flex item with &lt;code&gt;collapse&lt;/code&gt; applied will be hidden, and its space freed in the main axis but not the cross-axis. Why? That remains an unsolved mystery... &lt;a href="https://stackoverflow.com/questions/42252682/whats-the-difference-between-visibility-hidden-and-visibility-collapse-in-flex" rel="noopener noreferrer"&gt;This StackOverflow question&lt;/a&gt; features a good set of examples&lt;sup id="fnref1"&gt;1&lt;/sup&gt; showing how &lt;code&gt;collapse&lt;/code&gt; works with flex items.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;The specific response with examples mentions Firefox and Edge as the two browsers where &lt;code&gt;collapse&lt;/code&gt; makes a difference for flex elements. However, this answer is six years old, and I suspect it refers to pre-Chromium-based Edge. The current Edge browser renders &lt;code&gt;visibility: collapse&lt;/code&gt; similarly to &lt;code&gt;visibility: hidden&lt;/code&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>CSS Word Soup: align, self, and justify items and content</title>
      <dc:creator>Fidel Leal</dc:creator>
      <pubDate>Thu, 20 Jul 2023 17:53:41 +0000</pubDate>
      <link>https://dev.to/fleal/css-word-soup-align-self-and-justify-items-and-content-45hp</link>
      <guid>https://dev.to/fleal/css-word-soup-align-self-and-justify-items-and-content-45hp</guid>
      <description>&lt;h6&gt;
  
  
  Every time I use Flexbox or Grid, I end up mixing—and messing—my spacing properties. Enough is enough! I decided to put together this post to save my&lt;em&gt;self&lt;/em&gt; some MDN skimming. From today on, I will have no excuse to &lt;em&gt;justify&lt;/em&gt; any mis&lt;em&gt;align&lt;/em&gt;ed element!
&lt;/h6&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Flexbox
&lt;/h3&gt;

&lt;p&gt;In the case of Flexbox,  the names for the properties that control alignment across the main and cross axes begin with  &lt;code&gt;justify&lt;/code&gt;  and  &lt;code&gt;align&lt;/code&gt;, respectively. However, the second part of the property name is different for each axis. Flex items are organized horizontally&lt;sup id="fnref1"&gt;1&lt;/sup&gt; with  &lt;code&gt;justify-&lt;/code&gt;&lt;em&gt;content&lt;/em&gt;, while &lt;code&gt;align-&lt;/code&gt;&lt;em&gt;items&lt;/em&gt; controls the vertical organization. There is also  &lt;code&gt;align-&lt;/code&gt;&lt;em&gt;self&lt;/em&gt;, which allows an element to override its assigned  &lt;code&gt;align-items&lt;/code&gt;  and align itself along the vertical axis independently from other elements inside the same container. An important caveat is that &lt;code&gt;align-self&lt;/code&gt; will be ignored when &lt;code&gt;margin&lt;/code&gt; for the element is set to &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Things start to get a bit tricky when we want to have an item override its assigned placement on the horizontal axis in the same way  &lt;code&gt;align-self&lt;/code&gt;  does for the vertical axis. In this case, you may think that  &lt;code&gt;justify-self&lt;/code&gt;  is a thing in Flexbox, but as it turns out, it isn’t! The way to accomplish that effect is no other than the good old  &lt;code&gt;margin&lt;/code&gt;  property. Try to use  &lt;code&gt;justify-self&lt;/code&gt;  inside a flex container and you will quickly realize that the property is ignored altogether. The same goes for  &lt;code&gt;justify-items&lt;/code&gt;, a property used in Grid and block-level layouts but ignored in the context of a flex container.&lt;/p&gt;

&lt;p&gt;Last, there is &lt;code&gt;align-content&lt;/code&gt;. The property does have an effect in Flexbox but only when &lt;code&gt;flex-wrap&lt;/code&gt; is set to &lt;code&gt;wrap&lt;/code&gt; or &lt;code&gt;wrap-reverse&lt;/code&gt;. In those cases, &lt;code&gt;align-content&lt;/code&gt; controls the vertical distribution and spacing of the wrapped lines of elements. If &lt;code&gt;flex-wrap&lt;/code&gt; is not set (the default value is &lt;code&gt;nowrap&lt;/code&gt;), a browser will ignore &lt;code&gt;align-content&lt;/code&gt; for that specific container.&lt;/p&gt;

&lt;p&gt;For the case my future self does not have the time to read through the above explanation, here is a handy table compiled from MDN's CSS pages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flexbox Property&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Controls how the browser distributes space between and around items along the main axis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Controls the alignment of items on the cross-axis. Another way to think about it: sets the &lt;code&gt;align-self&lt;/code&gt; value on all the container's direct children as a group.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Overrides a flex item's &lt;code&gt;align-items&lt;/code&gt; value. This item will be independently aligned on the cross-axis. &lt;strong&gt;Important&lt;/strong&gt;: if a flexbox item's cross-axis &lt;code&gt;margin&lt;/code&gt; is &lt;code&gt;auto&lt;/code&gt;, then &lt;code&gt;align-self&lt;/code&gt; is ignored.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the distribution of space between and around content items along a flexbox's cross-axis or a grid's block axis. This property does not affect single-line flex containers (i.e. ones with &lt;code&gt;flex-wrap: nowrap&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This property is ignored in Flexbox.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This property is ignored in Flexbox.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Grid
&lt;/h3&gt;

&lt;p&gt;Now onto Grid!&lt;/p&gt;

&lt;p&gt;Contrary to the case with Flex, all six properties discussed above have an application in Grid. The naming of properties in the Grid model is more consistent with how they work, making it easier to understand their proper use.&lt;/p&gt;

&lt;p&gt;The properties ending in &lt;code&gt;-content&lt;/code&gt; apply to the grid container (content -&amp;gt; container!). The names work similarly to the way they do in Flexbox when the &lt;code&gt;flex-direction&lt;/code&gt; is set to &lt;code&gt;row&lt;/code&gt;: &lt;code&gt;justify-content&lt;/code&gt; applies to the spacing and positioning of the &lt;em&gt;grid cells&lt;/em&gt; on the main axis, and &lt;code&gt;align-content&lt;/code&gt; does the same for the cross axis&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. &lt;/p&gt;

&lt;p&gt;The pair of properties ending in &lt;code&gt;-items&lt;/code&gt; also apply to the grid containers. However, they control spacing for the elements  &lt;em&gt;inside&lt;/em&gt; the grid cells. &lt;/p&gt;

&lt;p&gt;Finally (finally!) the pair of properties ending in &lt;code&gt;-self&lt;/code&gt; apply —very appropriately— not to the grid container but to individual grid items. It allows them to override the &lt;code&gt;-items&lt;/code&gt; property set for their container and choose their own alignment.&lt;/p&gt;

&lt;p&gt;As with Flexbox, here is a little table of the properties and their effect:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;   Flexbox Property&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to the grid container. Controls the alignment of grid items along the main axis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to the grid container.Controls the alignment of grid lines along the cross-axis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to the grid container. Controls the alignment of grid items along the main axis &lt;em&gt;within each grid cell&lt;/em&gt;. Sets the default alignment for all grid items in the container.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to the grid container. Controls the alignment of grid items along the cross-axis &lt;em&gt;within each grid cell&lt;/em&gt;. Sets the default alignment for all grid items in the container.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to grid items. Controls the alignment of a specific grid item along the main axis within its grid, allowing it to override the alignment set by &lt;code&gt;justify-items&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applies to grid items. Controls the alignment of a specific grid item along the cross-axis within its grid, allowing it to override the alignment set by &lt;code&gt;align-items&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  More on this topic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/32551291/in-css-flexbox-why-are-there-no-justify-items-and-justify-self-properties"&gt;In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/27539262/whats-the-difference-between-align-content-and-align-items"&gt;What's the difference between align-content and align-items?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://saturncloud.io/blog/in-css-flexbox-why-are-there-no-justifyitems-and-justifyself-properties/"&gt;In CSS Flexbox why are there no justify-items and justify-self properties (different article)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;If &lt;code&gt;flex-direction&lt;/code&gt; is set to &lt;code&gt;column&lt;/code&gt;, the axes exchange their orientation (the main axis will be horizontal and the cross-axis vertical). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;There is no such thing as a &lt;code&gt;grid-direction&lt;/code&gt; property in Grid. So, properties beginning with &lt;code&gt;justify&lt;/code&gt; always apply to the horizontal axis, and the ones starting with &lt;code&gt;align&lt;/code&gt; always affect the vertical axis. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
  </channel>
</rss>
