The other day I was browsing a clothing shop website, and a headline caught my attention. When I found out that it was part of an image, I thought, mhmhmh, why not recreate this with code for fun!

Coincidentally, the following days I saw a few people on Twitter talking about what they wrote with the #postAboutYourPen, and found @rachsmith encouraging challenge, thus I thought maybe it's time to write my first post and take part of such challenge.

Table of contents

  1. The image headline
  2. The headline recreation
  3. How was the headline recreated?
    3.1 HTML
    3.2 CSS
    3.3 JS
  4. To conclude

The image headline

In the following image you'll see the headline I wanted to recreate with code.

Image credit: Zara Shop

The headline recreation

In the following pen you'll find the result of my creation with code, where the headline can also be edited.

How was the headline recreated?

I'll walk you step by step on how I was able to achieve this with bits of HTML, CSS and JS.

1. HTML

Let's start with the HTML.

I wanted to recreate the headline not only as a static element, but with the feature of allowing editing. I wanted to be able to test different headline names.

And so an <input type="text"> element made sense to my opinion.


Update: 03/Nov/17

I didn't use a heading element like <h1> with a contenteditable attribute, because I wanted to have a placeholder and maxlength attributes within the HTML element, instead of adding them via CSS and/or JS.


I also decided to wrap such input field into another container <div class="headline">, so that I could manipulate easier it's alignment on the layout I had in mind.

I added <span class="c-block"> element to place a background image in the layout.

Finally, I created another <div class="u-hidden"> where I was planning to duplicate the text entered on the input field, for styling purposes.

  <div class="headline">
  <input type="text" name="headline" placeholder="new" maxlength="7" class="c-input-headline" id="is-headline"/>
</div>
<span class="c-block"></span>
<div class="c-input-headline u-hidden" id="is-duplicate"></div>

2. CSS

Let's continue with the CSS and break it down into three parts.

Beware that I'll explain the CSS code via SCSS.


2.1 SCSS Part 1

Like almost everybody else, I usually start coding my SCSS from general to specific.

And I like to start by defining the variables I think I might need to build what I want.

Of course, many of the first variables defined end up having another value once I am done building a certain object or component. But during the creation process, it's easier to always come back and edit such variables if I want to change anything. Whether if it's a simply color change, or the whole size of a certain CSS property.

Lately, I started to build prototypes and play with mostly native CSS variables, thus in this case all variables I defined have the following syntax: --native_css_variable.

Once I'm done with all variables, I continue by defining my SCSS mixins including group of CSS properties I can think I'll see myself re-defining over and over again in different selectors.

Lastly, I define the CSS properties and values I need in general layout elements like the <body>.

FYI: The ::placeholder pseudo element has the CSS property and value of opacity: 1;. I added this because weirdly enought, Firefox was displaying the input placeholder with some opacity in contrast with Chrome and Safari. If you want to test it, make sure to comment the opacity in such browsers and you'll see what I mean.

  :root {
    // COLOR CSS VARIABLES
    --color_txt: #090707; // Black
    --color_base: #fff; // White
    --color_block: #e8e8e8; // Grey
    --color_accent: #ff1d8e; // Neon Pink
    --color_marker: #c9ff42; // Neon Yellow

    // SIZE CSS VARIABLES
    --font_size: 10em; // Resize headline by only editing this variable
    --height: calc(var(--font_size) * 1.35);
}

// MIXINS
@mixin size($w, $h: $w) {
    width: $w;
    height: $h;
}

// LAYOUT
body {
    background-color: var(--color_base);
}

::placeholder {
    color: var(--color_txt);
    opacity: 1; // Needed for Firefox
}

::selection {
    background-color: var(--color_marker);
}

2.2 SCSS Part 2

Following next, in this case, I targeted styling the wrapper of the headline I wanted to build, <div class="headline">.

Then, I styled the main component of this prototype which was the headline defined via HTML as <input type="text" class="c-input-headline"/>.

You'll notice below that in order to add the main side-cut effect at the top of the headline, I use the clip-path CSS property. And declared a value of polygon(100% 10%, -112% 100%, 100% 90%);.

If you ever want to explore more the clip-path CSS property, I find this online tool CSS clip-path maker quite useful.

FYI: The input headline and duplicated headline share the class name .c-input-headline, because I needed that the duplicated headline own the exact same styles as the input headline, in order to measure the precise width of the text entered by the user, given that the width of the text entered on the input field cannot be measure via JS later on.

  <input type="text" class="c-input-headline"/>
<div class="c-input-headline u-hidden">

In the end of this step, I styled the container I created to duplicate the text entered on the input field, which has the utiliity class name of .u-hidden, since I don't want to show this duplicated headline as part of the layout. I only needed it in order to measure the full-width of the text entered, every time, on the input field. Read more in the JS Section.

  // HEADLINE WRAPPER
.headline {
    @include size(100%, var(--height));
    margin-top: 10%;
    text-align: center;
    overflow: hidden;
}

// HEADLINE INPUT FIELD
// HEADLINE DUPLICATE
.c-input-headline {
    @include size(100%);
    border: 0;
    background-color: transparent;
    caret-color: var(--color_accent); // Not supported yet in Safari or IE
    color: var(--color_txt);
    display: inline-block; // Needed to get precise text width
    font-family: "Oswald", sans-serif;
    font-size: var(--font_size);
    letter-spacing: 0.02em;
    margin: 0;
    padding: 0;
    text-align: center;
    text-transform: uppercase;
    clip-path: polygon(100% 10%, -112% 100%, 100% 90%); // Not supported yet in IE

    &:focus {
        outline: none;
    }
}

// HEADLINE DUPLICATE
    // Exists for JS purposes
.u-hidden {
    width: auto;
    opacity: 0;
    visibility: hidden;
    position: fixed;
}

2.3 SCSS Part 3

The final SCSS styles were basically adding the mood background image I chose, to go along with this headline recreation.

You'll find I used the transform: scaleX(-1);, in order to flip the image horizontally, as the object focus of the image was on the far left, and I wanted to have it on the opposite side instead.

  // BACKGROUND IMG BLOCK
.c-block {
    @include size(47vw, 100vh);
    background-color: var(--color_block);
    background-image: url('https://images.pexels.com/photos/403571/pexels-photo-403571.jpeg?w=940&h=650&dpr=2&auto=compress&cs=tinysrgb');
    background-position: 100% 0;
    background-size: cover;
    position: fixed;
    top: 0;
    left: 0;
    transform: scaleX(-1); // Needed to mirror the original image, as I wanted the cactus displayed on the far right
    z-index: -1;
}

3. JS

At last, let's take a look at the JS, and also break it down into three parts.

Beware that the JS code was pure vanilla.


3.1 JS Part 1

Since I wanted to add one particular feature via JS, I started by creating a function expression for such feature, and named it observeInputText.

  var observeInputText = function () {};
observeInputText();

Inside that function, I firstly defined the variables I thought I might need in more than one child function.

  var observeInputText = function () {

    var $inputHeadline = document.getElementById('is-headline'),
        $headlineVal   = document.getElementById('is-duplicate');

};

observeInputText();

3.2 JS Part 2

Then, I continued by building two child functions, updateInputWidth and updatePlaceholderWidth, which are pretty self explanatory, thus read the comments in the code to follow through.

  var observeInputText = function () {

    function updateInputWidth() {
        // Get precise width of div elem containing the input placeholder/value duplicate
        var inputWidth = $headlineVal.clientWidth + 'px';

        // Add precise width of that div elem into the input field
        $inputHeadline.style.width = inputWidth;
    }

    function updatePlaceholderWidth() { 
        // Duplicate placeholder text into another container, a div elem
        $headlineVal.innerText = $inputHeadline.getAttribute('placeholder');

        updateInputWidth();
    }

};

observeInputText();

3.3 JS Part 3

To finalize, I created the last child function, listenInputText, which makes sure that every time the user edits the headline, by typing new text, the side-cut effect at the top is styled proporcionally according to the width of such text entered.

I decided that the side-cut effect should always be proportional to the exact width of the text, because otherwise the effect didn't look as sleek, nor the same, if the user entered more than three characters, used in the original headline, "NEW".

  var observeInputText = function () {

    function listenInputText() {
        var $inputTxtVal = $inputHeadline.value;

        // Duplicate value/text entered on input field into another container, a div elem
        $headlineVal.innerText = $inputTxtVal;

        updateInputWidth();

        // Add default width to input field if no text has been entered
        if ($inputTxtVal === '') {
            updatePlaceholderWidth();
        }
    }

    updatePlaceholderWidth();
    $inputHeadline.addEventListener('keyup', listenInputText, false);

};

observeInputText();

To conclude

Review all together again in the pen I built, or browse the table of contents.

Enjoy playing with this headline feature!

And thanks for the read. :)

If you have any kind of feedback, or opinion on how this headline idea or post can be improved, just drop me a comment below.

Happy coding!


3,435 0 4