国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
The game
The HTML structure
Creating maps for shape data
Using mixins to read from maps
Start logic
Home Web Front-end CSS Tutorial Breaking Boundaries: Building a Tangram Puzzle With (S)CSS

Breaking Boundaries: Building a Tangram Puzzle With (S)CSS

Jun 13, 2025 am 11:33 AM

Breaking Boundaries: Building a Tangram Puzzle With (S)CSS

For years, I believed that drag-and-drop games — especially those involving rotation, spatial logic, and puzzle solving — were the exclusive domain of JavaScript. Until one day, I asked AI:

“Is it possible to build a fully interactive Tangram puzzle game using only CSS?”

The answer:“No — not really. You’ll need JavaScript.” That was all the motivation I needed to prove otherwise.

But first, let’s ask the obvious question:Why would anyone do this?

Well…

  • To know how far CSS can be pushed in creating interactive UIs.
  • To get better at my CSS skills.
  • And it’s fun!

Fair enough?

Now, here’s the unsurprising truth: CSS isn’t exactly made for this. It’s not a logic language, and let’s be honest, it’s not particularly dynamic either. (Sure, we have CSS variables and some handy built-in functions now, hooray!)

In JavaScript, we naturally think in terms of functions, loops, conditions, objects, comparisons. We write logic, abstract things into methods, and eventually ship a bundle that the browser understands. And once it’s shipped? We rarely look at that final JavaScript bundle — we just focus on keeping it lean.

Now ask yourself: isn’t that exactly what Sass does for CSS?

Why should we hand-write endless lines of repetitive CSS when we can use mixins and functions to generate it — cleanly, efficiently, and without caring how many lines it takes, as long as the output is optimized?

So, we put it to the test and it turns out Sass can replace JavaScript, at least when it comes to low-level logic and puzzle behavior. With nothing but maps, mixins, functions, and a whole lot of math, we managed to bring our Tangram puzzle to life, no JavaScript required.

Let the (CSS-only) games begin! ??

The game

The game consists of seven pieces: the classic Tangram set. Naturally, these pieces can be arranged into a perfect square (and many other shapes, too). But we need a bit more than just static pieces.

So here’s what I am building:

  • A puzzle goal, which is the target shape the player has to recreate.
  • A start button that shuffles all the pieces into a staging area.
  • Each piece is clickable and interactive.
  • The puzzle should let the user know when they get a piece wrong and also celebrate when they finish the puzzle.

The HTML structure

I started by setting up the HTML structure, which is no small task, considering the number of elements involved.

  • Each shape was given seven radio buttons. I chose radios over checkboxes to take advantage of their built-in exclusivity. Only one can be selected within the same group. This made it much easier to track which shape and state were currently active.
  • The start button? Also a radio input. A checkbox could’ve worked too, but for the sake of consistency, I stuck with radios across the board.
  • The puzzle map itself is just a plain old
    , simple and effective.
  • For rotation, we added eight radio buttons, each representing a 45-degree increment: 45°, 90°, 135°, all the way to 360°. These simulate rotation controls entirely in CSS.
  • Every potential shadow position got its own radio button too. (Yes, it’s a lot, I know.)
  • And to wrap it all up, I included a classic reset button inside a
    using
  • Given the sheer number of elements required, I used Pug to generate the HTML more efficiently. It was purely a convenience choice. It doesn’t affect the logic or behavior of the puzzle in any way.

    Below is a sample of the compiled HTML. It might look overwhelming at first glance (and this is just a portion of it!), but it illustrates the structural complexity involved. This section is collapsed to not nuke your screen, but it can be expanded if you’d like to explore it.

    Open HTML Code
    <div>
      <div></div>
      <div></div>
      <form>
        <input type="checkbox" autofocus>
        <button type="reset">Restart</button>
        <label for="start">Start </label>
        <div>
          <input type="radio" name="tan-active">
          <input type="radio" name="tan-active">
          <!-- Inputs for others tans -->
          <input type="radio" name="tan-active">
          <input type="radio" name="tan-rotation">
          <input type="radio" name="tan-rotation">
          <!--radios for 90, 225, 315, 360 -->
    
          <input type="checkbox" name="tan-rotation">
          <input type="checkbox" name="tan-rotation">
          <!-- radio for every possible shape shadows-->
    
          <label for="rotation-45">?</label>
          <label for="rotation-90">?</label>
          <!--radios for 90, 225, 315, 360 -->
          <label for="rotation-reset">?</label>
    
          <label for="blueTriangle-tan"></label>
          <div></div>
          <!-- labels for every tan and disabled div -->
    
          <label for="blueTriangle-tan-1-90"></label>
          <label for="blueTriangle-tan-1-225"></label>
          <!-- labels radio for every possible shape shadows-->
          <div></div>
        </div>
      </form>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>

    Creating maps for shape data

    Now that HTML skeleton is ready, it’s time to inject it with some real power. That’s where ourSass mapscome in, and here’s where the puzzle logic starts to shine.

    Note: Maps in Sass hold pairs of keys and values, and make it easy to look up a value by its corresponding key. Like objects in JavaScript, dictionaries in Python and, well, maps in C .

    I’m mapping out all the core data needed to control each tangram piece (tan): its color, shape, position, and even interaction logic. These maps contain:

    • thebackground-colorfor each tan,
    • theclip-pathcoordinates that define their shapes,
    • the initial position for each tan,
    • the position of the blockingdiv(which disables interaction when a tan is selected),
    • the shadow positions (coordinates for the tan’s silhouette displayed on the task board),
    • the grid information, and
    • the winning combinations — the exact target coordinates for each tan, marking the correct solution.
    $colors: ( blue-color: #53a0e0, yellow-color: #f7db4f, /* Colors for each tan */ );
    $nth-child-grid: ( 1: (2, 3, 1, 2, ), 2: ( 3, 4, 1, 2, ), 4: ( 1, 2, 2, 3, ), /* More entries to be added */);
    $bluePosiblePositions: ( 45: none, 90: ( (6.7, 11.2), ), 135: none, 180: none, /* Positions defined up to 360 degrees */);
    /* Other tans */
    
    /* Data defined for each tan */
    $tansShapes: (
      blueTriangle: (
        color: map.get($colors, blue-color),
        clip-path: ( 0 0, 50 50, 0 100, ),
        rot-btn-position: ( -20, -25, ),
        exit-mode-btn-position: ( -20, -33, ),
        tan-position: ( -6, -37, ),
        diable-lab-position: ( -12, -38, ),
        poss-positions: $bluePosiblePositions,
        correct-position: ((4.7, 13.5), (18.8, 13.3), ),
        transform-origin: ( 4.17, 12.5,),
      ),
    );
    
    /* Remaining 7 combinations */
    $winningCombinations: (
      combo1: (
        (blueTriangle, 1, 360),
        (yellowTriangle, 1, 225),
        (pinkTriangle, 1, 180),
        (redTriangle, 4, 360),
        (purpleTriangle, 2, 225),
        (square, 1, 90),
        (polygon, 4, 90),
      ),
    );

    You can see this in action on CodePen, where these maps drive the actual look and behavior of each puzzle piece. At this point, there’s no visible change in the preview. We’ve simply prepared and stored the data for later use.

    Using mixins to read from maps

    The main idea is to create reusable mixins that will read data from the maps and apply it to the corresponding CSS rules when needed.

    But before that, we’ve elevated things to a higher level by making one key decision: We never hard-coded units directly inside the maps. Instead, we built a reusable utility function that dynamically adds the desired unit (e.g.,vmin,px, etc.) to any numeric value when it’s being used. This way, when can use our maps however we please.

    @function get-coordinates($data, $key, $separator, $unit) {
      $coordinates: null;
    
      // Check if the first argument is a map
      @if meta.type-of($data) == "map" {
        // If the map contains the specified key
        @if map.has-key($data, $key) {
          // Get the value associated with the key (expected to be a list of coordinates)
          $coordinates: map.get($data, $key);
        }
    
      //  If the first argument is a list
      } @else if meta.type-of($data) == "list" {
        // Ensure the key is a valid index (1-based) within the list
        @if meta.type-of($key) == "number" and $key > 0 and $key 
    
    
    
    <p>Sure, nothing’s showing up in the preview yet, but the real magic starts now.</p>
    
    
    
    
    
    
    
    <p>Now we move on to writing mixins. I’ll explain the approach in detail for the first mixin, and the rest will be described through comments.</p>
    
    
    
    <p>The first mixin dynamically appliesgrid-columnandgrid-rowplacement rules to child elements based on values stored in a map. Each entry in the map corresponds to an element index (1 through 8) and contains a list of four values:[start-col, end-col, start-row, end-row].</p>
    
    
    
    <pre rel="SCSS" data-line="">@mixin tanagram-grid-positioning($nth-child-grid) {
      // Loop through numbers 1 to 8, corresponding to the tanam pieces
      @for $i from 1 through 8 {
    
        // Check if the map contains a key for the current piece (1-8)
        @if map.has-key($nth-child-grid, $i) {
    
          // Get the grid values for this piece: [start-column, end-column, start-row, end-row]
          $values: map.get($nth-child-grid, $i);
    
          // Target the nth child (piece) and set its grid positions
          &:nth-child(#{$i}) {
            // Set grid-column: start and end values based on the first two items in the list
            grid-column: #{list.nth($values, 1)} / #{list.nth($values, 2)};
    
            // Set grid-row: start and end values based on the last two items in the list
            grid-row: #{list.nth($values, 3)} / #{list.nth($values, 4)};
          }
        }
      }
    }

    We can expect the following CSS to be generated:

    .tanagram-box:nth-child(1) {
      grid-column: 2 / 3;
      grid-row: 1 / 2;
    }
    
    .tanagram-box:nth-child(2) {
      grid-column: 3 / 4;
      grid-row: 1 / 2;
    }

    In this mixin, my goal was actually to create all the shapes (tans). I am usingclip-path. There were ideas to use fancy SVG images, but this test project is more about testing the logic rather than focusing on beautiful design. For this reason, the simplest solution was to cut the elements according to dimensions while they are still in the square (the initial position of all the tans).

    So, in this case, through a static calculation, the$tansShapesmap was updated with theclip-pathproperty:

    clip-path: (0 0, 50 50, 0 100);

    This contains the clip points for all the tans. In essence, this mixin shapes and colors each tan accordingly.

    @mixin set-tan-clip-path($tanName, $values) {
      //  Initialize an empty list to hold the final clip-path points
      $clip-path-points: ();
    
      // Extract the 'clip-path' data from the map, which contains coordinate pairs
      $clip-path-key: map.get($values, clip-path);
    
      // Get the number of coordinate pairs to loop through
      $count: list.length($clip-path-key);
    
      //  Loop through each coordinate point
      @for $i from 1 through $count {
        //  Convert each pair of numbers into a formatted coordinate string with units
        $current-point: get-coordinates($clip-path-key, $i, " ", "%");
    
        //  Add the formatted coordinate to the list, separating each point with a comma
        $clip-path-points: list.append($clip-path-points, #{$current-point}, comma);
      }
    
      //  Style for the preview element (lab version), using the configured background color
      #tan#{$tanName}lab {
        background: map.get($values, color);
        clip-path: polygon(#{$clip-path-points}); // Apply the full list of clip-path points
      }
    
      //  Apply the same clip-path to the actual tan element
      .#{$tanName} {
        clip-path: polygon(#{$clip-path-points});
      }
    }

    and output in CSS should be:

    .blueTriangle {
      clip-path: polygon(0% 0%, 50% 50%, 0% 100%);
    }
    /* other tans */

    Start logic

    Alright, now I’d like to clarify what should happen first when the game loads.

    First, with a click on the Start button, all the tans“go to their positions.” In reality, we assign them atransform: translate()with specific coordinates and a rotation.

    .start:checked ~ .shadow #tanblueTrianglelab {
      transform-origin: 4.17vmin 12.5vmin;
      transform: translate(-6vmin,-37vmin) rotate(360deg);
      cursor: pointer;
    }

    So, we still maintain this pattern. We use transform and simply change the positions or angles (in the maps) of both the tans and their shadows on the task board.

    When any tan is clicked, the rotation button appears. By clicking on it, the tan should rotate around its center, and this continues with each subsequent click. There are actually eight radio buttons, and with each click, one disappears and the next one appears. When we reach the last one, clicking it makes it disappear and the first one reappears. This way, we get the impression of clicking the same button (they are, of course, styled the same) and being able to click (rotate the tan) infinitely. This is exactly what the following mixin enables.

    @mixin set-tan-rotation-states($tanName, $values, $angles, $color) {
      // This mixin dynamically applies rotation UI styles based on a tan's configuration.
      // It controls the positioning and appearance of rotation buttons and visual feedback when a rotation state is active.
      @each $angle in $angles{
        & ~ #rot#{$angle}{ transform: translate(get-coordinates($values,rot-btn-position,',',vmin )); background: $color;}
        & ~ #rotation-#{$angle}:checked{
          @each $key in map.keys($tansShapes){
            & ~ #tan#{$key}labRes{ visibility: visible; background:rgba(0,0,0,0.4); }
            & ~ #tan#{$key}lab{ opacity:.3; }
            & ~ #rotReset{ visibility: visible; }
          } 
        }
      }
    }

    And the generated CSS should be:

    #blueTriangle-tan:checked ~ #rotation-45:checked ~ #tanblueTrianglelab {
      transform: translate(-6vmin,-37vmin) rotate(45deg);
    }
    
    #blueTriangle-tan:checked ~ #rotation-45:checked ~ #tanblueTrianglelabRes {
      visibility: hidden;
    }

    OK, the following mixins use theset-clip-pathandset-rotationmixins. They contain all the information about the tans and their behavior in relation to which tan is clicked and which rotation is selected, as well as their positions (as defined in the second mixin).

    @mixin generate-tan-shapes-and-interactions($tansShapes) {
    // Applies styling logic and UI interactions for each individual tan shape from the $tansShapes map.
      @each $tanName, $values in $tansShapes{
        $color: color.scale(map.get($values, color), $lightness: 10%); 
        $angles: (45, 90, 135, 180, 225, 270, 315, 360); 
        @include set-tan-clip-path($tanName, $values);
    
        ##{$tanName}-tan:checked{
          & ~ #tan#{$tanName}Res{ visibility:hidden; }
          & ~ #tan#{$tanName}lab{opacity: 1 !important;background: #{$color};cursor:auto;}
          @each $key in map.keys($tansShapes){
              & ~ #tan#{$tanName}Res:checked ~ #tan#{$key}labRes{visibility: visible;}
          }
          & ~  #rot45{display: flex;visibility: visible;}
          & ~ #rotReset{ transform: translate(get-coordinates($values, exit-mode-btn-position,',', vmin)); }
          @include set-tan-rotation-states($tanName, $values, $angles, $color);
        }  
      }
    }
    @mixin set-initial-tan-position($tansShapes) {
    // This mixin sets the initial position and transformation for both the interactive (`lab`) and shadow (`labRes`) versions
    // of each tan shape, based on coordinates provided in the $tansShapes map.
     @each $tanName, $values in $tansShapes{
        & ~ .shadow #tan#{$tanName}lab{
          transform-origin: get-coordinates($values, transform-origin,' ' ,vmin);
          transform: translate( get-coordinates($values,tan-position,',', vmin)) rotate(360deg) ;
          cursor: pointer;
        }
        & ~ .shadow #tan#{$tanName}labRes{
          visibility:hidden;
          transform: translate(get-coordinates($values,diable-lab-position,',',vmin)); 
        }
      }
    }

    As mentioned earlier, when a tan is clicked, one of the things that becomes visible is its shadow — a silhouette that appears on the task board.

    These shadow positions (coordinates) are currently defined statically. Each shadow has a specific place on the map, and a mixin reads this data and applies it to the shadow usingtransform: translate().

    When the clicked tan is rotated, the number of visible shadows on the task board can change, as well as their angles, which is expected.

    Of course, special care was taken with naming conventions. Each shadow element gets a unique ID, made from the name (inherited from its parent tan) and a number that represents its sequence position for the given angle.

    Pretty cool, right? That way, we avoid complicated naming patterns entirely!

    @mixin render-possible-tan-positions( $name, $angle, $possiblePositions, $visibility, $color, $id, $transformOrigin ) {
        // This mixin generates styles for possible positions of a tan shape based on its name, rotation angle, and configuration map.
        // It handles both squares and polygons, normalizing their rotation angles accordingly and applying transform styles if positions exist.}
      @if $name == 'square' {
        $angle: normalize-angle($angle); // Normalizujemo ugao ako je u pitanju square
      } @else if $name == 'polygon'{
        $angle: normalize-polygon-angle($angle);
      }
      @if map.has-key($possiblePositions, $angle) {
        $values: map.get($possiblePositions, $angle);
    
        @if $values != none {
          $count: list.length($values);
    
          @for $i from 1 through $count {
            $position: get-coordinates($values, $i, ',', vmin);
            & ~ #tan#{$name}lab-#{$i}-#{$angle} { 
              @if $visibility == visible {
                visibility: visible;
                background-color: $color;
                opacity: .2;
                z-index: 2;
                transform-origin: #{$transformOrigin};
                transform: translate(#{$position}) rotate(#{$angle}deg);
              } @else if $visibility == hidden { visibility: hidden; }
              &:hover{ opacity: 0.5; cursor: pointer; }
            }
          }
        }
      }
    }

    The generated CSS:

    #blueTriangle-tan:checked ~ #tanblueTrianglelab-1-360 {
      visibility: visible;
      background-color: #53a0e0;
      opacity: 0.2;
      z-index: 2;
      transform-origin: 4.17vmin 12.5vmin;
      transform: translate(4.7vmin,13.5vmin) rotate(360deg);
    }

    This next mixin is tied to the previous one and manages when and how the tan shadows appear while their parent tan is being rotated using the button. It listens for the current rotation angle and checks whether there are any shadow positions defined for that specific angle. If there are, it displays them; if not — no shadows!

    @mixin render-possible-positions-by-rotation {
       // This mixin applies rotation to each tan shape. It loops through each tan, calculates its possible positions for each angle, and handles visibility and transformation.
       // It ensures that rotation is applied correctly, including handling the transitions between various tan positions and visibility states.
     @each $tanName, $values in $tansShapes{
        $possiblePositions: map.get($values, poss-positions);
        $possibleTansColor: map.get($values, color);
        $validPosition: get-coordinates($values, correct-position,',' ,vmin);
        $transformOrigin: get-coordinates($values,transform-origin,' ' ,vmin); 
        $rotResPosition: get-coordinates($values,exit-mode-btn-position ,',' ,vmin );
        $angle: 0;
        @for $i from 1 through 8{
          $angle: $i * 45;
          $nextAngle: if($angle   45 > 360, 45, $angle   45);
          @include render-position-feedback-on-task($tanName,$angle, $possiblePositions,$possibleTansColor, #{$tanName}-tan, $validPosition,$transformOrigin, $rotResPosition);   
            ##{$tanName}-tan{
            @include render-possible-tan-positions($tanName,$angle, $possiblePositions,hidden, $possibleTansColor, #{$tanName}-tan,$transformOrigin)
          }
            ##{$tanName}-tan:checked{
              @include render-possible-tan-positions($tanName,360, $possiblePositions,visible, $possibleTansColor, #{$tanName}-tan,$transformOrigin);
              & ~ #rotation-#{$angle}:checked {
                @include render-possible-tan-positions($tanName,360, $possiblePositions,hidden, $possibleTansColor, #{$tanName}-tan,$transformOrigin);
                & ~ #tan#{$tanName}lab{transform:translate( get-coordinates($values,tan-position,',', vmin))  rotate(#{$angle}deg) ;}
                & ~ #tan#{$tanName}labRes{ visibility: hidden; }
                & ~ #rot#{$angle}{ visibility: hidden; }
                & ~ #rot#{$nextAngle}{ visibility: visible } 
                @include render-possible-tan-positions($tanName,$angle, $possiblePositions,visible, $possibleTansColor, #{$tanName}-tan,$transformOrigin);
            }
          }
        }
      }
    }

    When a tan’s shadow is clicked, the corresponding tan should move to that shadow’s position. The next mixin then checks whether this new position is the correct one for solving the puzzle. If it is correct, the tan gets a brief blinking effect and becomes unclickable, signaling it’s been placed correctly. If it’s not correct, the tan simply stays at the shadow’s location. There’s no effect and it remains draggable/clickable.

    Of course, there’s a list of all the correct positions for each tan. Since some tans share the same size — and some can even combine to form larger, existing shapes — we have multiple valid combinations. For this Camel task, all of them were taken into account. A dedicated map with these combinations was created, along with a mixin that reads and applies them.

    At the end of the game, when all tans are placed in their correct positions, we trigger a “merging” effect — and the silhouette of the camel turns yellow. At that point, the only remaining action is to click the Restart button.

    Well, that was long, but that’s what you get when you pick the fun (albeit hard and lengthy) path. All as an ode to CSS-only magic!

The above is the detailed content of Breaking Boundaries: Building a Tangram Puzzle With (S)CSS. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How can I include CSS only on some pages? How can I include CSS only on some pages? Jun 11, 2025 am 12:01 AM

There are three ways to selectively include CSS on a specific page: 1. Inline CSS, suitable for pages that are not frequently accessed or require unique styles; 2. Load external CSS files using JavaScript conditions, suitable for situations where flexibility is required; 3. Containment on the server side, suitable for scenarios using server-side languages. This approach can optimize website performance and maintainability, but requires balance of modularity and performance.

Flexbox vs Grid: Understanding the Key Differences in CSS Layout Flexbox vs Grid: Understanding the Key Differences in CSS Layout Jun 10, 2025 am 12:03 AM

Flexboxisidealforone-dimensionallayouts,whileGridsuitstwo-dimensional,complexlayouts.UseFlexboxforaligningitemsinasingleaxisandGridforprecisecontroloverrowsandcolumnsinintricatedesigns.

Creating an Auto-Closing Notification With an HTML Popover Creating an Auto-Closing Notification With an HTML Popover Jun 10, 2025 am 09:45 AM

The HTML popover attribute transforms elements into top-layer elements that can be opened and closed with a button or JavaScript. Popovers can be dismissed a number of ways, but there is no option to auto-close them. Preethi has a technique you can u

What is 'render-blocking CSS'? What is 'render-blocking CSS'? Jun 24, 2025 am 12:42 AM

CSS blocks page rendering because browsers view inline and external CSS as key resources by default, especially with imported stylesheets, header large amounts of inline CSS, and unoptimized media query styles. 1. Extract critical CSS and embed it into HTML; 2. Delay loading non-critical CSS through JavaScript; 3. Use media attributes to optimize loading such as print styles; 4. Compress and merge CSS to reduce requests. It is recommended to use tools to extract key CSS, combine rel="preload" asynchronous loading, and use media delayed loading reasonably to avoid excessive splitting and complex script control.

How to use Lotties in Figma How to use Lotties in Figma Jun 14, 2025 am 10:17 AM

In the following tutorial, I will show you how to create Lottie animations in Figma. We'll use two colorful designs to exmplify how you can animate in Figma, and then I'll show you how to go from Figma to Lottie animations. All you need is a free Fig

Breaking Boundaries: Building a Tangram Puzzle With (S)CSS Breaking Boundaries: Building a Tangram Puzzle With (S)CSS Jun 13, 2025 am 11:33 AM

We put it to the test and it turns out Sass can replace JavaScript, at least when it comes to low-level logic and puzzle behavior. With nothing but maps, mixins, functions, and a whole lot of math, we managed to bring our Tangram puzzle to life, no J

External vs. Internal CSS: What's the Best Approach? External vs. Internal CSS: What's the Best Approach? Jun 20, 2025 am 12:45 AM

ThebestapproachforCSSdependsontheproject'sspecificneeds.Forlargerprojects,externalCSSisbetterduetomaintainabilityandreusability;forsmallerprojectsorsingle-pageapplications,internalCSSmightbemoresuitable.It'scrucialtobalanceprojectsize,performanceneed

Does my CSS must be on lower case? Does my CSS must be on lower case? Jun 19, 2025 am 12:29 AM

No,CSSdoesnothavetobeinlowercase.However,usinglowercaseisrecommendedfor:1)Consistencyandreadability,2)Avoidingerrorsinrelatedtechnologies,3)Potentialperformancebenefits,and4)Improvedcollaborationwithinteams.

See all articles