/ Gists

Gists

On gists

triangles in CSS (3 ways)

CSS CSS trick

index.css #

/* https://htmixl.medium.com/how-to-create-triangles-in-css-three-easy-ways-49bd6dce7810 */

/* 1. borders */
.triangle{
 width: 0;
 height: 0;
 border-left: 150px solid red;
 border-top: 150px solid transparent;
}

/* 2. clip-path */
.triangle{
  width: 150px;
  height: 150px;
  background-color: blue;
  clip-path: polygon(0 0, 0 100%, 100% 100%);
}

/* 3. gradient */
.triangle{
  width: 150px;
  height: 150px;
  background-image: 
    linear-gradient(to top right, green 50%, transparent 0);
  background-repeat: no-repeat;
}

On gists

ResizeObserver.html

JavaScript

ResizeObserver.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>

        <style>
            .container {
                display: flex;
                width: 100%; /* This can be changed via the buttons. */
                height: 200px;
                padding: 8px;
                background: #eaeaea;
            }

            /* Image Wrappers */
            .container > div {
                height: 200px;
                min-width: 100px;
                max-width: 200px;
                flex: 1;
                background-size: cover;
                background-repeat: no-repeat;
            }

            /* The rest is just setup. */

            #app {
                display: flex;
                flex-direction: column;
                align-items: center;
                font-family: sans-serif;
                padding: 16px;
            }

            p {
                margin-top: 32px;
                text-align: center;
                color: #4c11f7;
                text-transform: uppercase;
                font-weight: 600;
                font-size: 14px;
                letter-spacing: 0.5px;
            }

            .change-size {
                display: flex;
                align-items: center;
                justify-content: center;
                flex-wrap: wrap;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="container"></div>

            <p>Container Size</p>
            <div class="change-size">
                <button value="100%">100%</button>
                <button value="1400px">1400px</button>
                <button value="640px">640px</button>
                <button value="200px">200px</button>
            </div>
        </div>

        <script>
            /* Attach ResizeObserver to the container. */
            const resizeObserver = new ResizeObserver(onResize);
            resizeObserver.observe(document.querySelector('.container'));

            const IMAGE_MAX_WIDTH = 200;
            const IMAGE_MIN_WIDTH = 100;

            function onResize(entries) {
                const entry = entries[0];
                const container = entry.target;
                /* Calculate how many images can fit in the container. */
                const imagesNeeded = Math.ceil(entry.contentRect.width / IMAGE_MAX_WIDTH);
                let images = container.children;

                console.log(images);

                /* Remove images as needed. */
                while (images.length > imagesNeeded) {
                    images[images.length - 1].remove();
                }
                /* Add images as needed. */
                while (images.length < imagesNeeded) {
                    let seed = Math.random().toString().replace('.', '');
                    const newImage = document.createElement('div');
                    const imageUrl = `https://picsum.photos/seed/${seed}/${IMAGE_MAX_WIDTH}`;
                    newImage.style.backgroundImage = `url(${imageUrl})`;
                    container.append(newImage);
                }
            }

            /* The rest is for the container size buttons. */
            function changeSize(e) {
                if (!e.target.value) return;
                const container = document.querySelector('.container');
                container.style.width = e.target.value;
            }

            const changeSizeButtons = document.querySelector('.change-size');
            changeSizeButtons.addEventListener('click', changeSize);
        </script>
    </body>
</html>

On gists

Resize Observer : only as many images what i need in limited container

JavaScript

ResizeObserver.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>

        <style>
            .container {
                display: flex;
                width: 100%; /* This can be changed via the buttons. */
                height: 200px;
                padding: 8px;
                background: #eaeaea;
            }

            /* Image Wrappers */
            .container > div {
                height: 200px;
                min-width: 100px;
                max-width: 200px;
                flex: 1;
                background-size: cover;
                background-repeat: no-repeat;
            }

            /* The rest is just setup. */

            #app {
                display: flex;
                flex-direction: column;
                align-items: center;
                font-family: sans-serif;
                padding: 16px;
            }

            p {
                margin-top: 32px;
                text-align: center;
                color: #4c11f7;
                text-transform: uppercase;
                font-weight: 600;
                font-size: 14px;
                letter-spacing: 0.5px;
            }

            .change-size {
                display: flex;
                align-items: center;
                justify-content: center;
                flex-wrap: wrap;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="container"></div>

            <p>Container Size</p>
            <div class="change-size">
                <button value="100%">100%</button>
                <button value="1400px">1400px</button>
                <button value="640px">640px</button>
                <button value="200px">200px</button>
            </div>
        </div>

        <script>
            /* Attach ResizeObserver to the container. */
            const resizeObserver = new ResizeObserver(onResize);
            resizeObserver.observe(document.querySelector('.container'));

            const IMAGE_MAX_WIDTH = 200;
            const IMAGE_MIN_WIDTH = 100;

            function onResize(entries) {
                const entry = entries[0];
                const container = entry.target;
                /* Calculate how many images can fit in the container. */
                const imagesNeeded = Math.ceil(entry.contentRect.width / IMAGE_MAX_WIDTH);
                let images = container.children;

                console.log(images);

                /* Remove images as needed. */
                while (images.length > imagesNeeded) {
                    images[images.length - 1].remove();
                }
                /* Add images as needed. */
                while (images.length < imagesNeeded) {
                    let seed = Math.random().toString().replace('.', '');
                    const newImage = document.createElement('div');
                    const imageUrl = `https://picsum.photos/seed/${seed}/${IMAGE_MAX_WIDTH}`;
                    newImage.style.backgroundImage = `url(${imageUrl})`;
                    container.append(newImage);
                }
            }

            /* The rest is for the container size buttons. */
            function changeSize(e) {
                if (!e.target.value) return;
                const container = document.querySelector('.container');
                container.style.width = e.target.value;
            }

            const changeSizeButtons = document.querySelector('.change-size');
            changeSizeButtons.addEventListener('click', changeSize);
        </script>
    </body>
</html>

On gists

Mounted teleport

Vue.js

MountedTeleport.vue #

<!--https://stackoverflow.com/questions/63652288/does-vue-3-teleport-only-works-to-port-outside-vue-->

<template>
    <Teleport :to="to" v-if="isMounted"><slot></slot></Teleport>
</template>

<script>
export default {
    name: "MountedTeleport",
    props: ['to'],
    data() {
        return {isMounted: false}
    },
    mounted() {
        this.isMounted = true;
    }
}
</script>

On gists

Computed with delay, resize window

Vue.js

app.vue #

<!-- https://codepen.io/sandrarodgers/pen/porZbxW --> 

<template>
  <div id="app">
    <div>Height: {{ height }}</div>
    <div>Width: {{ width }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      debouncedHeight: 0,
      debouncedWidth: 0,
      heightTimeout: null,
      widthTimeout: null
    };
  },
  computed:  {
	  height:  {
		  get()  {
			  return  this.debouncedHeight;
		  },
		  set(val)  {
			  if  (this.timeout)  clearTimeout(this.timeout);
			  this.heightTimeout =  setTimeout(()  =>  {
				  this.debouncedHeight = val;
				},  5000);
			}
		},
		width:  {
		  get()  {
			  return  this.debouncedWidth;
		  },
		  set(val)  {
			  if  (this.timeout)  clearTimeout(this.timeout);
			  this.widthTimeout =  setTimeout(()  =>  {
				  this.debouncedWidth = val;
				},  5000);
			}
		},
	},
  methods: {
    resizeHandler(e) {
      this.height = window.innerHeight;
      this.width = window.innerWidth;
    },
  },
  mounted() {
    this.height = window.innerHeight;
    this.width = window.innerWidth;
  },
  created() {
    window.addEventListener("resize", this.resizeHandler);
  },
  destroyed() {
    window.removeEventListener("resize", this.resizeHandler);
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  font-size: 1.5rem;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

On gists

Nette: Admin LastUserEdit Trait

Nette

LastEditTrait.php #

<?php

trait FastAdminLastChangeTrait {

	/**
	 * Bootstrap trait
	 * 
	 * @return void
	 */
	public function injectFastAdminLastChangeTrait()
	{
		$this->onBeforeSave[] = function($editRow, $values, $form) { 
            $values['lastchange'] = new \DateTime();
            $values['lastchange__user_id'] = $this->getUser()->getId();
        };

        $this->onCreateForm[] = function($form) 
        {
            if(isset($form['lastchange'])) 
                $form['lastchange']->getControlPrototype()->addClass('deactivateInput');

            if(isset($form['lastchange__user_id'])) 
                $form['lastchange__user_id']->getControlPrototype()->addClass('deactivateInput');
        };
	}


}

On gists

CSS Clamp builder (responsive fluid typography)

JavaScript CSS CSS trick

clampBuilder.js #

// https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/#for-those-who-dont-mind-that-edge-case
// https://royalfig.github.io/fluid-typography-calculator/
// https://fluid-typography.netlify.app/

function clampBuilder( minWidthPx, maxWidthPx, minFontSize, maxFontSize ) {
  const root = document.querySelector( "html" );
  const pixelsPerRem = Number( getComputedStyle( root ).fontSize.slice( 0,-2 ) );

  const minWidth = minWidthPx / pixelsPerRem;
  const maxWidth = maxWidthPx / pixelsPerRem;

  const slope = ( maxFontSize - minFontSize ) / ( maxWidth - minWidth );
  const yAxisIntersection = -minWidth * slope + minFontSize

  return `clamp( ${ minFontSize }rem, ${ yAxisIntersection }rem + ${ slope * 100 }vw, ${ maxFontSize }rem )`;
}


console.log(clampBuilder(320, 1920, 1, 3)); // "clamp( 1rem, 0.6rem + 2vw, 3rem )"

On gists

Fast fill array

JavaScript JS oneliners

fast-fill.js #

const newData = Array(20)
      .fill(0)
      .map((_, index) =>  index++);

On gists

Intersection observer (infinity scroll)

JavaScript Web Api

demo.js #

// https://levelup.gitconnected.com/what-is-intersection-observer-api-and-how-is-it-useful-1e91a14579df
// https://codepen.io/ohdylan/pen/ZExqKzx



let secondLastChild = document.querySelectorAll('.box:nth-last-child(2)')[0];
let boxes = document.querySelector('.boxes')
const mockFetchMoreBoxes = () => {
    const startIndex = parseInt(secondLastChild.textContent.replace('Test Element', '')) + 2
    for(let i = startIndex; i < startIndex + 20; i++) {
        const newBox = document.createElement('div')
        newBox.textContent = `Test Element ${i}`
        newBox.classList.add('box')
        boxes.append(newBox)
        if(i == startIndex + 18) {
            observer.unobserve(secondLastChild)
            secondLastChild = newBox
            observer.observe(secondLastChild);
        }
    }
}

let observer = new IntersectionObserver((entries) => {
    console.log(entries[0])
    const secondLastChild = entries[0]
    if(secondLastChild.isIntersecting){
        return mockFetchMoreBoxes()
    }
}, {})

observer.observe(secondLastChild);

On gists

Grid full-bleeding, full width

CSS trick

example.css #

/*

https://fatbuddhadesigns.co.uk/journal/full-bleed-layouts/
https://www.joshwcomeau.com/css/full-bleed/
https://blog.logrocket.com/full-bleed-layout-css-grid/

*/




.wrapper {
  display: grid;
  grid-template-columns: 1fr min(60ch, calc(100% - 64px)) 1fr;
  grid-column-gap: 32px;
}


.full-bleed {
  grid-column: 1 / -1;
}


.full-bleed {
  width: 100%;
  grid-column: 1 / 4;
}