ESK shapes poc

In this example below you will see how to do a ESK shapes poc with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by megatronCGN, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright megatronCGN ©
  • HTML
  • CSS
  • JavaScript
    <div class="container">
	<!-- Schräge an einer Kante -->
	<div class="esk-shape esk-shape--has-image esk-shape--b-rl">
		<div class="esk-shape__inner">
			<div class="esk-shape__image-container" role="presentation">
				<img class="esk-shape__image" src="https://images.unsplash.com/photo-1498323094960-d1a30fae4c5c?auto=format&fit=crop&w=1950&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D">
			</div>
			<strong>Bottom Right to Left (b-rl)</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<div class="esk-shape esk-shape--t-lr">
		<div class="esk-shape__inner">
			<div class="wf-accordion js-accordion js-accordion--is-expanded">
				<div class="wf-accordion__header js-accordion__header">
					<div class="wf-accordion__trigger js-accordion-trigger">
						<strong>Bottom Left to Right as Accordion</strong>

					</div>
				</div>
				<div class="wf-accordion__panel js-accordion__panel">

					<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und
						dir Projekte anbieten.</p>

				</div>
			</div>
		</div>
	</div>
	<div class="esk-shape esk-shape--b-lr">
		<div class="esk-shape__inner">
			<strong>Bottom Left to Right</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<div class="esk-shape esk-shape--t-rl">
		<div class="esk-shape__inner">
			<strong>Top Right to Left</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<!-- Schräge an zwei Kanten -->
	<div class="esk-shape esk-shape--b-a-l">
		<div class="esk-shape__inner">
			<strong>Bottom Left</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<div class="esk-shape esk-shape--t-a-l">
		<div class="esk-shape__inner">
			<strong>Top Left</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<div class="esk-shape esk-shape--b-a-r">
		<div class="esk-shape__inner">
			<strong>Bottom Right</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
	<div class="esk-shape esk-shape--t-a-r">
		<div class="esk-shape__inner">
			<strong>Top Right</strong>
			<p>Du registrierst dich bei der EU als Mitglied des Solidaritätskorps' und gibst an, was dich interessiert und welche Erfahrungen du bereits mitbringst. Danach kannst du dich auf freie Plätze bewerben, Organisationen können dich aber auch finden und dir
				Projekte anbieten.</p>
		</div>
	</div>
</div>

/*Downloaded from https://www.codeseek.co/megatronCGN/esk-shapes-poc-BYyKbZ */
    $unit: 24px;

* {
	box-sizing: border-box;
}

body {
	min-height: 100vh;
	padding: $unit*2;
	display: flex;
	font-size: 20px;
	line-height: 1.5;
	
	> div {
		max-width: 1024px;
		margin: auto;
	}
}

p {
	margin: 0;
	
	* + &,
	& + * {
		margin-top: .75em;
	}
}

.esk-shape {
	$shape-unit: 1.5;
	$deg: $shape-unit * 1deg;
	
	position: relative;
	overflow: hidden;
	
	&[class*="--t"] + [class*="--b"] {
		margin-top: $shape-unit*1.75%;
	}
	
	.esk-shape__inner {
		padding: $unit;
	}
	
	&.esk-shape--has-image {
		height: 600px;
	}
	
	&:not(.esk-shape--has-image)::before,
	.esk-shape__image-container {
		content: '';
		width: 100%;
		height: 100%;
		position: absolute;
		top: 0;
		left: 0;
		z-index: -1;
		background-color: #009CDE;
	}
	
	.esk-shape__image-container {
		background-color: transparent;
		overflow: hidden;		
	}
	
	.esk-shape__image {
		width: 100%;
		height: 100%;
		position: absolute;
		top: 0;
		left: 0;
		object-fit: cover;
		background: linear-gradient(red 0%, red 50%, blue 50%);
	}
		
	&.esk-shape--t-lr {
	
		.esk-shape__inner {
			padding-top: $unit*$shape-unit;
		}
		
		&::before,
	.esk-shape__image-container {			
			transform: skewX(-$deg) rotate(-$deg);
			transform-origin: top right;
		}
	}
		
	&.esk-shape--t-rl {
	
		.esk-shape__inner {
			padding-top:  $unit*$shape-unit/2;
		}
		
		&::before,
		.esk-shape__image-container {			
			transform: skewX($deg) rotate($deg);
			transform-origin: top left;
		}
	}
		
	&.esk-shape--b-lr {
	
		.esk-shape__inner {
			padding-bottom:  $unit*$shape-unit;
		}
		
		&::before,
	.esk-shape__image-container {			
			transform: skewX($deg) rotate($deg);
			transform-origin: top right;
		}
	}
		
	&.esk-shape--b-rl {
	
		.esk-shape__inner {
			padding-bottom:  $unit*$shape-unit;
		}
		
		&::before,
		.esk-shape__image-container {			
			transform: skewX(-$deg) rotate(-$deg);
			transform-origin: top left;
		}
		
		.esk-shape__image {			
			transform: skewX($deg) rotate(	$deg);
			transform-origin: top left;
		}
	}
		
	&.esk-shape--t-a-l {
	
		.esk-shape__inner {
			padding-top:  $unit*$shape-unit;
			padding-left: $unit*2;
		}
		
		&::before,
	.esk-shape__image-container {			
			transform: skewX($deg) rotate(-$deg);
			transform-origin: top right;
		}
	}
		
	&.esk-shape--t-a-r {
	
		.esk-shape__inner {
			padding-top:  $unit*$shape-unit/2;
			padding-right: $unit*2;
		}
		
		&::before,
	.esk-shape__image-container {			
			transform: skewX(-$deg) rotate($deg);
			transform-origin: top left;
		}
	}
		
	&.esk-shape--b-a-l {
	
		.esk-shape__inner {
			padding-left: $unit*2;
			padding-bottom:  $unit*$shape-unit;
		}
		
		&::before,
		.esk-shape__image-container {			
			transform: skewX($deg) rotate(-$deg);
			transform-origin: top left;
		}
	} 
		
	&.esk-shape--b-a-r {
	
		.esk-shape__inner {
			padding-right: $unit*2;
			padding-bottom:  $unit*$shape-unit;
		}
		
		&::before,
	.esk-shape__image-container {			
			transform: skewX(-$deg) rotate($deg);
			transform-origin: top right;
		}
	}
}



/*Downloaded from https://www.codeseek.co/megatronCGN/esk-shapes-poc-BYyKbZ */
    /**
 * wf.accordion.js
 * @file jQuery Plugin zum Enhancen von vordefiniertem Markup mit Akkordeonfunktion
 * (barrierearm und inkl. Tastaturunterstützung)
 *
 * @example Benötigtes HTML:
 * <div class="wf-accordion js-accordion js-accordion--is-expanded">
 *     <div class="wf-accordion__header js-accordion__header">
 *         <div class="wf-accordion__trigger js-accordion-trigger">Titel</div>
 *     </div>
 *     <div class="wf-accordion__panel js-accordion__panel">Text</div>
 * </div>
 *
 * Anmerkungen:
 * - Bei Bedarf kann der Akkordeon-Trigger im HTML selbstverständlich auch eine Überschrift (z.B. <h2>) sein; zu beachten ist
 *   hier, dass der Trigger bei aktivem JS unabhängig vom Ausgangs-HTML zu einem Button umgewandelt wird (das <h2> wäre daher nur
 *   bei ausgeschaltetem JS relevant). Die visuelle Anzeige sollte nicht vom Element sondern nur von der Styling-Klasse abhängen!
 * - Die Styling- und JS-Hook-Klassen sind frei wählbar, letztere (.js-*) müssen allerdings an das Plugin via Options übergeben werden,
 *   sobald sie von den Namen im Beispiel abweichen
 * - Akkordeons können via Klasse auf dem äußeren Container optional geöffnet initialisiert werden (default: .js-accordion--is-expanded)
 *
 * Unterstützte Tastatureingaben:
 * - Sämtliche Interaktive Elemente folgen der normalen Tab ⇥ Reihenfolge (Akkordeon-Trigger sind ansteuerbar, offene Panels
 *   erlauben das Ansteuern von Links etc. innerhalb der Panels)
 * - Sobald ein Akkordeon :focus hat (z. B. durch Tab ⇥), können die verschiedenen Akkordeon-Trigger mit den
 *   Pfeiltasten ↑↓ durchnavigiert werden
 * - Die Page Up ↖ / Page Down ↘ Tasten erlauben den Sprung zum ersten bzw. letzten Akkordeon-Trigger
 * - Die Akkordeon-Trigger reagieren auf Leertaste und Enter ↵, um ein Akkordeon-Panel zu öffnen bzw. zu schließen
 */
(function($) {
    'use strict';

    /**
     * Erzeuge Counter zur Erstellung eindeutiger IDs
     * @type {number}
     */
    var counter = 0;

    /**
     * wfAccordion Plugin Definition
     * @param {Object} [options]
     */
    $.fn.wfAccordion = function(options) {

        var defaults = {
            context: 'body',
            accordionHeader: '.js-accordion__header',
            accordionTrigger: '.js-accordion__trigger',
            accordionPanel: '.js-accordion__panel',
            accordionIsOpenClass: 'js-accordion--is-expanded'
        };

        // Erzeuge settings aus defaults und ggf. übergebenen Optionsparametern
        var settings = $.extend({}, defaults, options);

        var $context = $(settings.context);
        var $accordionHeaders = $context.find(settings.accordionHeader);

        $accordionHeaders.each(function(index, header) {
            var $header = $(header);
            var $triggerPlaceholder = $header.find(settings.accordionTrigger);
            var $panel = $header.next(settings.accordionPanel);

            var $trigger = replaceWithButton($triggerPlaceholder);

            // Enhance Trigger und Panel mit a11y Attributen
            $trigger.attr('aria-expanded', false);
            $panel.attr('aria-hidden', true);

            // Erzeuge eindeutige IDs für a11y Beziehung
            var headerId = 'accordion-' + counter + '__header-' + index;
            var panelId = 'accordion-' + counter +  '__panel-' + index;

            // Erzeuge a11y Beziehungen zwischen Header und Panel
            $trigger.attr('aria-controls', panelId);
            $panel.attr('id', panelId);

            $trigger.attr('id', headerId);
            $panel.attr('aria-labelledby', headerId);

            // Initialisiere als offen designierte Akkordeons
            if ($header.parent().hasClass(settings.accordionIsOpenClass)) {
                $trigger.attr('aria-expanded', true);
                $panel.attr('aria-hidden', false)
            }

            // Aktualisiere ARIA states bei Klick/Tap
            $trigger.on('click', function(event) {
                var $target = $(event.target);
                var state = $target.attr('aria-expanded') === 'false';

                $target.attr('aria-expanded', state);
                $('#' + $target.attr('aria-controls')).attr('aria-hidden', !state);
            });

            // Unterstütze Tastatureingabe
            $trigger.on('keydown', function(event) {
                var $target = $(event.target);
                var key = event.which.toString();
                var $header = $target.parent(settings.accordionHeader);

                // 33 = Page Up, 34 = Page Down
                var ctrlModifier = (event.ctrlKey && key.match(/33|34/));

                // Unterstützung von Up / Down Pfeil sowie Ctrl + Page Up / Page Down Tasten
                // 38 = Up, 40 = Down
                if (key.match(/38|40/) || ctrlModifier) {
                    var index = $accordionHeaders.index($header);
                    var direction = (key.match(/34|40/)) ? 1 : -1;
                    var length = $accordionHeaders.length;
                    var newIndex = (index + length + direction) % length;

                    $($accordionHeaders[newIndex]).find(settings.accordionTrigger).focus();

                    event.preventDefault();
                } else if (key.match(/35|36/)) {
                    // Unterstützung von 35 = End, 36 = Home Tasten
                    switch (key) {
                        // Fokussiere das erste Akkordeon-Element
                        case '36':
                            $($accordionHeaders[0]).find(settings.accordionTrigger).focus();
                            break;
                        // Fokussiere das letzte Akkordeon-Element
                        case '35':
                            $($accordionHeaders[$accordionHeaders.length - 1]).find(settings.accordionTrigger).focus();
                            break;
                    }

                    event.preventDefault();
                }
            });
        });

        // Jeder Aufruf des Plugins erhöht den Counter
        counter++;
    };

    /**
     * Ersetzt Platzhalter-Element durch <button>-Element für optimierte Tastaturbedienbarkeit
     *
     * @param {jQuery} $placeholder
     * @returns {jQuery}
     */
    function replaceWithButton($placeholder) {
        var $button = $('<button>' + $placeholder.text() + '</button>');

        $.each(getAttributes($placeholder), function(key, value) {
            $button.attr(key, value);
        });

        $placeholder.replaceWith($button);

        return $button;
    }

    /**
     * Gibt alle HTML-Attribute eines jQuery Objekts zurück
     * @param {jQuery} $node
     * @returns {{}}
     */
    function getAttributes ($node) {
        var attrs = {};
        $.each( $node[0].attributes, function (index, attribute) {
            attrs[attribute.name] = attribute.value;
        } );

        return attrs;
    }
	
	$('.js-accordion').wfAccordion();

})(jQuery); 


Comments