[Special Summer Sale] 40% OFF All Magento 2 Themes

Cart

Is it possible to apply CSS to half of a character?

  • This topic is empty.
Viewing 15 posts - 1 through 15 (of 21 total)
  • Author
    Posts
  • #9115
    David Hoang
    Keymaster

    What I am looking for:

    A way to style one HALF of a character. (In this case, half the letter being transparent)

    What I have currently searched for and tried (With no luck):

    • Methods for styling half of a character/letter
    • Styling part of a character with CSS or JavaScript
    • Apply CSS to 50% of a character

    Below is an example of what I am trying to obtain.

    x

    Does a CSS or JavaScript solution exist for this, or am I going to have to resort to images? I would prefer not to go the image route as this text will end up being generated dynamically.


    UPDATE:

    Since many have asked why I would ever want to style half of a character, this is why. My city had recently spent $250,000 to define a new “brand” for itself. This logo is what they came up with. Many people have complained about the simplicity and lack of creativity and continue to do so. My goal was to come up with this website as a joke. Type in ‘Halifax’ and you will see what I mean.

    #9129
    David Hoang
    Keymaster

    Closest I can get:

    $(function(){
      $('span').width($('span').width()/2);
      $('span:nth-child(2)').css('text-indent', -$('span').width());
    });
    body{
      font-family: arial;
    }
    span{
      display: inline-block;
      overflow: hidden;
    }
    span:nth-child(2){
      color: red;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <span>X</span><span>X</span>

    Demo: http://jsfiddle.net/9wxfY/2/

    Heres a version that just uses one span: http://jsfiddle.net/9wxfY/4/

    #9134
    David Hoang
    Keymaster

    enter image description here

    I’ve just finished developing the plugin and it is available for everyone to use! Hope you will enjoy it.

    View Project on GitHub – View Project Website. (so you can see all the split styles)

    Usage

    First of all, make sure you have the jQuery library is included. The best way to get the latest jQuery version is to update your head tag with:

    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    

    After downloading the files, make sure you include them in your project:

    <link rel="stylesheet" type="text/css" href="css/splitchar.css">
    <script type="text/javascript" src="js/splitchar.js"></script>
    

    Markup

    All you have to do is to asign the class splitchar , followed by the desired style to the element wrapping your text. e.g

    <h1 class="splitchar horizontal">Splitchar</h1>
    

    After all this is done, just make sure you call the jQuery function in your document ready file like this:

    $(".splitchar").splitchar();
    

    Customizing

    In order to make the text look exactly as you want it to, all you have to do is apply your design like this:

    .horizontal { /* Base CSS - e.g font-size */ }
    .horizontal:before { /* CSS for the left half */ }
    .horizontal:after { /* CSS for the right half */ }
    

    That’s it! Now you have the Splitchar plugin all set. More info about it at http://razvanbalosin.com/Splitchar.js/.

    #9132
    David Hoang
    Keymaster

    Example


    JSFiddle DEMO

    We’ll do it using just CSS pseudo selectors!

    This technique will work with dynamically generated content and different font sizes and widths.

    HTML:

    <div class='split-color'>Two is better than one.</div>
    

    CSS:

    .split-color > span {
        white-space: pre-line;
        position: relative;
        color: #409FBF;
    }
    
    .split-color > span:before {
        content: attr(data-content);
        pointer-events: none;  /* Prevents events from targeting pseudo-element */
        position: absolute;
        overflow: hidden;
        color: #264A73;
        width: 50%;
        z-index: 1;
    }
    

    To wrap the dynamically generated string, you could use a function like this:

    // Wrap each letter in a span tag and return an HTML string
    // that can be used to replace the original text
    function wrapString(str) {
      var output = [];
      str.split('').forEach(function(letter) {
        var wrapper = document.createElement('span');
        wrapper.dataset.content = wrapper.innerHTML = letter;
    
        output.push(wrapper.outerHTML);
      });
    
      return output.join('');
    }
    
    // Replace the original text with the split-color text
    window.onload = function() {
        var el  = document.querySelector('.split-color'),
            txt = el.innerHTML;
        
        el.innerHTML = wrapString(txt);
    }
    
    #9126
    David Hoang
    Keymaster

    Limited CSS and jQuery Solution

    I am not sure how elegant this solution is, but it cuts everything exactly in half: http://jsfiddle.net/9wxfY/11/

    Otherwise, I have created a nice solution for you… All you need to do is have this for your HTML:

    Take a look at this most recent, and accurate, edit as of 6/13/2016 : http://jsfiddle.net/9wxfY/43/

    As for the CSS, it is very limited… You only need to apply it to :nth-child(even)

    $(function(){
      var $hc = $('.half-color');
      var str = $hc.text();
      $hc.html("");
    
      var i = 0;
      var chars;
      var dupText;
    
      while(i < str.length){
        chars = str[i];
        if(chars == " ") chars = "&nbsp;";
        dupText = "<span>" + chars + "</span>";
    
        var firstHalf = $(dupText);
        var secondHalf = $(dupText);
    
        $hc.append(firstHalf)
        $hc.append(secondHalf)
    
        var width = firstHalf.width()/2;
    
        firstHalf.width(width);
        secondHalf.css('text-indent', -width);
    
        i++;
      }
    });
    .half-color span{
      font-size: 2em;
      display: inline-block;
      overflow: hidden;
    }
    .half-color span:nth-child(even){
      color: red;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="half-color">This is a sentence</div>
    #9135
    David Hoang
    Keymaster

    Now on GitHub as a Plugin!

    enter image description here Feel free to fork and improve.

    Demo | Download Zip | Half-Style.com (Redirects to GitHub)


    • Pure CSS for a Single Character
    • JavaScript used for automation across text or multiple characters
    • Preserves Text Accessibility for screen readers for the blind or visually
      impaired

    Part 1: Basic Solution

    Half Style on text

    Demo: http://jsfiddle.net/arbel/pd9yB/1694/


    This works on any dynamic text, or a single character, and is all automated. All you need to do is add a class on the target text and the rest is taken care of.

    Also, the accessibility of the original text is preserved for screen readers for the blind or visually impaired.

    Explanation for a single character:

    Pure CSS. All you need to do is to apply .halfStyle class to each element that contains the character you want to be half-styled.

    For each span element containing the character, you can create a data attribute, for example here data-content="X", and on the pseudo element use content: attr(data-content); so the .halfStyle:before class will be dynamic and you won’t need to hard code it for every instance.

    Explanation for any text:

    Simply add textToHalfStyle class to the element containing the text.


    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    .halfStyle {
        position: relative;
        display: inline-block;
        font-size: 80px; /* or any font size will work */
        color: black; /* or transparent, any color */
        overflow: hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
    }
    
    .halfStyle:before {
        display: block;
        z-index: 1;
        position: absolute;
        top: 0;
        left: 0;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        color: #f00;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)


    Part 2: Advanced solution – Independent left and right parts

    Half Style on text - advanced - With Text Shadow

    With this solution you can style left and right parts, individually and independently.

    Everything is the same, only more advanced CSS does the magic.

    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
            $el = $(el);
            text = $el.text();
            chars = text.split('');
    
            // Set the screen-reader text
            $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
            // Reset output for appending
            output = '';
    
            // Iterate over all chars in the text
            for (i = 0; i < chars.length; i++) {
                // Create a styled element for each character and append to container
                output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
            }
    
            // Write to DOM only once
            $el.append(output);
        });
    });
    .halfStyle {
        position: relative;
        display: inline-block;
        font-size: 80px; /* or any font size will work */
        color: transparent; /* hide the base character */
        overflow: hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
    }
    
    .halfStyle:before { /* creates the left part */
        display: block;
        z-index: 1;
        position: absolute;
        top: 0;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #f00; /* for demo purposes */
        text-shadow: 2px -2px 0px #af0; /* for demo purposes */
    }
    
    .halfStyle:after { /* creates the right part */
        display: block;
        direction: rtl; /* very important, will make the width to start from right */
        position: absolute;
        z-index: 2;
        top: 0;
        left: 50%;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #000; /* for demo purposes */
        text-shadow: 2px 2px 0px #0af; /* for demo purposes */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)



    Part 3: Mix-Match and Improve

    Now that we know what is possible, let’s create some variations.


    -Horizontal Half Parts

    • Without Text Shadow:

      Horizontal Half Parts - No Text Shadow

    • Possibility of Text Shadow for each half part independently:

      halfStyle - Horizontal Half Parts - With Text Shadow

    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    .halfStyle {
      position: relative;
      display: inline-block;
      font-size: 80px; /* or any font size will work */
      color: transparent; /* hide the base character */
      overflow: hidden;
      white-space: pre; /* to preserve the spaces from collapsing */
    }
    
    .halfStyle:before { /* creates the top part */
      display: block;
      z-index: 2;
      position: absolute;
      top: 0;
      height: 50%;
      content: attr(data-content); /* dynamic content for the pseudo element */
      overflow: hidden;
      pointer-events: none; /* so the base char is selectable by mouse */
      color: #f00; /* for demo purposes */
      text-shadow: 2px -2px 0px #af0; /* for demo purposes */
    }
    
    .halfStyle:after { /* creates the bottom part */
      display: block;
      position: absolute;
      z-index: 1;
      top: 0;
      height: 100%;
      content: attr(data-content); /* dynamic content for the pseudo element */
      overflow: hidden;
      pointer-events: none; /* so the base char is selectable by mouse */
      color: #000; /* for demo purposes */
      text-shadow: 2px 2px 0px #0af; /* for demo purposes */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)



    -Vertical 1/3 Parts

    • Without Text Shadow:

      halfStyle - Vertical 1/3 Parts - No Text Shadow

    • Possibility of Text Shadow for each 1/3 part independently:

      halfStyle - Vertical 1/3 Parts - With Text Shadow

    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    .halfStyle { /* base char and also the right 1/3 */
        position: relative;
        display: inline-block;
        font-size: 80px; /* or any font size will work */
        color: transparent; /* hide the base character */
        overflow: hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
        color: #f0f; /* for demo purposes */
        text-shadow: 2px 2px 0px #0af; /* for demo purposes */
    }
    
    .halfStyle:before { /* creates the left 1/3 */
        display: block;
        z-index: 2;
        position: absolute;
        top: 0;
        width: 33.33%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #f00; /* for demo purposes */
        text-shadow: 2px -2px 0px #af0; /* for demo purposes */
    }
    
    .halfStyle:after { /* creates the middle 1/3 */
        display: block;
        z-index: 1;
        position: absolute;
        top: 0;
        width: 66.66%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #000; /* for demo purposes */
        text-shadow: 2px 2px 0px #af0; /* for demo purposes */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)



    -Horizontal 1/3 Parts

    • Without Text Shadow:

      halfStyle - Horizontal 1/3 Parts - No Text Shadow

    • Possibility of Text Shadow for each 1/3 part independently:

      halfStyle - Horizontal 1/3 Parts - With Text Shadow

    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    .halfStyle { /* base char and also the bottom 1/3 */
      position: relative;
      display: inline-block;
      font-size: 80px; /* or any font size will work */
      color: transparent;
      overflow: hidden;
      white-space: pre; /* to preserve the spaces from collapsing */
      color: #f0f;
      text-shadow: 2px 2px 0px #0af; /* for demo purposes */
    }
    
    .halfStyle:before { /* creates the top 1/3 */
      display: block;
      z-index: 2;
      position: absolute;
      top: 0;
      height: 33.33%;
      content: attr(data-content); /* dynamic content for the pseudo element */
      overflow: hidden;
      pointer-events: none; /* so the base char is selectable by mouse */
      color: #f00; /* for demo purposes */
      text-shadow: 2px -2px 0px #fa0; /* for demo purposes */
    }
    
    .halfStyle:after { /* creates the middle 1/3 */
      display: block;
      position: absolute;
      z-index: 1;
      top: 0;
      height: 66.66%;
      content: attr(data-content); /* dynamic content for the pseudo element */
      overflow: hidden;
      pointer-events: none; /* so the base char is selectable by mouse */
      color: #000; /* for demo purposes */
      text-shadow: 2px 2px 0px #af0; /* for demo purposes */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)



    -HalfStyle Improvement By @KevinGranger

    halfStyle - KevinGranger

    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    body {
        background-color: black;
    }
    
    .textToHalfStyle {
        display: block;
        margin: 200px 0 0 0;
        text-align: center;
    }
    
    .halfStyle {
        font-family: 'Libre Baskerville', serif;
        position: relative;
        display: inline-block;
        width: 1;
        font-size: 70px;
        color: black;
        overflow: hidden;
        white-space: pre;
        text-shadow: 1px 2px 0 white;
    }
    
    .halfStyle:before {
        display: block;
        z-index: 1;
        position: absolute;
        top: 0;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        color: white;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo)



    -PeelingStyle improvement of HalfStyle by @SamTremaine

    halfStyle - SamTremaine

    // jQuery for automated mode
    jQuery(function($) {
        var text, chars, $el, i, output;
    
        // Iterate over all class occurences
        $('.textToHalfStyle').each(function(idx, el) {
        $el = $(el);
        text = $el.text();
        chars = text.split('');
    
        // Set the screen-reader text
        $el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
    
        // Reset output for appending
        output = '';
    
        // Iterate over all chars in the text
        for (i = 0; i < chars.length; i++) {
            // Create a styled element for each character and append to container
            output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
        }
    
        // Write to DOM only once
        $el.append(output);
      });
    });
    .halfStyle {
        position: relative;
        display: inline-block;
        font-size: 68px;
        color: rgba(0, 0, 0, 0.8);
        overflow: hidden;
        white-space: pre;
        transform: rotate(4deg);
        text-shadow: 2px 1px 3px rgba(0, 0, 0, 0.3);
    }
    
    .halfStyle:before { /* creates the left part */
        display: block;
        z-index: 1;
        position: absolute;
        top: -0.5px;
        left: -3px;
        width: 100%;
        content: attr(data-content);
        overflow: hidden;
        pointer-events: none;
        color: #FFF;
        transform: rotate(-4deg);
        text-shadow: 0px 0px 1px #000;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <p>Single Characters:</p>
    <span class="halfStyle" data-content="X">X</span>
    <span class="halfStyle" data-content="Y">Y</span>
    <span class="halfStyle" data-content="Z">Z</span>
    <span class="halfStyle" data-content="A">A</span>
    
    <hr/>
    <p>Automated:</p>
    
    <span class="textToHalfStyle">Half-style, please.</span>

    (JSFiddle demo and on samtremaine.co.uk)



    Part 4: Ready for Production

    Customized different Half-Style style-sets can be used on desired elements on the same page.
    You can define multiple style-sets and tell the plugin which one to use.

    The plugin uses data attribute data-halfstyle="[-CustomClassName-]" on the target .textToHalfStyle elements and makes all the necessary changes automatically.

    So, simply on the element containing the text add textToHalfStyle class and data attribute data-halfstyle="[-CustomClassName-]". The plugin will do the rest of the job.

    halfStyle - Multiple on Same Page

    Also the CSS style-sets’ class definitions match the [-CustomClassName-] part mentioned above and is chained to .halfStyle, so we will have .halfStyle.[-CustomClassName-]

    jQuery(function($) {
        var halfstyle_text, halfstyle_chars, $halfstyle_el, halfstyle_i, halfstyle_output, halfstyle_style;
    
        // Iterate over all class occurrences
        $('.textToHalfStyle').each(function(idx, halfstyle_el) {
            $halfstyle_el = $(halfstyle_el);
            halfstyle_style = $halfstyle_el.data('halfstyle') || 'hs-base';
            halfstyle_text = $halfstyle_el.text();
            halfstyle_chars = halfstyle_text.split('');
    
            // Set the screen-reader text
            $halfstyle_el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + halfstyle_text + '</span>');
    
            // Reset output for appending
            halfstyle_output = '';
    
            // Iterate over all chars in the text
            for (halfstyle_i = 0; halfstyle_i < halfstyle_chars.length; halfstyle_i++) {
                // Create a styled element for each character and append to container
                halfstyle_output += '<span aria-hidden="true" class="halfStyle ' + halfstyle_style + '" data-content="' + halfstyle_chars[halfstyle_i] + '">' + halfstyle_chars[halfstyle_i] + '</span>';
            }
    
            // Write to DOM only once
            $halfstyle_el.append(halfstyle_output);
        });
    });
    /* start half-style hs-base */
    
    .halfStyle.hs-base {
        position: relative;
        display: inline-block;
        font-size: 80px; /* or any font size will work */
        overflow: hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
        color: #000; /* for demo purposes */
    }
    
    .halfStyle.hs-base:before {
        display: block;
        z-index: 1;
        position: absolute;
        top: 0;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        pointer-events: none; /* so the base char is selectable by mouse */
        overflow: hidden;
        color: #f00; /* for demo purposes */
    }
    
    /* end half-style hs-base */
    
    
    /* start half-style hs-horizontal-third */
    
    .halfStyle.hs-horizontal-third { /* base char and also the bottom 1/3 */
        position: relative;
        display: inline-block;
        font-size: 80px; /* or any font size will work */
        color: transparent;
        overflow: hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
        color: #f0f;
        text-shadow: 2px 2px 0px #0af; /* for demo purposes */
    }
    
    .halfStyle.hs-horizontal-third:before { /* creates the top 1/3 */
        display: block;
        z-index: 2;
        position: absolute;
        top: 0;
        height: 33.33%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #f00; /* for demo purposes */
        text-shadow: 2px -2px 0px #fa0; /* for demo purposes */
    }
    
    .halfStyle.hs-horizontal-third:after { /* creates the middle 1/3 */
        display: block;
        position: absolute;
        z-index: 1;
        top: 0;
        height: 66.66%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow: hidden;
        pointer-events: none; /* so the base char is selectable by mouse */
        color: #000; /* for demo purposes */
        text-shadow: 2px 2px 0px #af0; /* for demo purposes */
    }
    
    /* end half-style hs-horizontal-third */
    
    
    /* start half-style hs-PeelingStyle, by user SamTremaine on Stackoverflow.com */
    
    .halfStyle.hs-PeelingStyle {
      position: relative;
      display: inline-block;
      font-size: 68px;
      color: rgba(0, 0, 0, 0.8);
      overflow: hidden;
      white-space: pre;
      transform: rotate(4deg);
      text-shadow: 2px 1px 3px rgba(0, 0, 0, 0.3);
    }
    
    .halfStyle.hs-PeelingStyle:before { /* creates the left part */
      display: block;
      z-index: 1;
      position: absolute;
      top: -0.5px;
      left: -3px;
      width: 100%;
      content: attr(data-content);
      overflow: hidden;
      pointer-events: none;
      color: #FFF;
      transform: rotate(-4deg);
      text-shadow: 0px 0px 1px #000;
    }
    
    /* end half-style hs-PeelingStyle */
    
    
    /* start half-style hs-KevinGranger, by user KevinGranger on StackOverflow.com*/
    
    .textToHalfStyle.hs-KevinGranger {
      display: block;
      margin: 200px 0 0 0;
      text-align: center;
    }
    
    .halfStyle.hs-KevinGranger {
      font-family: 'Libre Baskerville', serif;
      position: relative;
      display: inline-block;
      width: 1;
      font-size: 70px;
      color: black;
      overflow: hidden;
      white-space: pre;
      text-shadow: 1px 2px 0 white;
    }
    
    .halfStyle.hs-KevinGranger:before {
      display: block;
      z-index: 1;
      position: absolute;
      top: 0;
      width: 50%;
      content: attr(data-content); /* dynamic content for the pseudo element */
      overflow: hidden;
      color: white;
    }
    
    /* end half-style hs-KevinGranger
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <p>
        <span class="textToHalfStyle" data-halfstyle="hs-base">Half-style, please.</span>
    </p>
    <p>
        <span class="textToHalfStyle" data-halfstyle="hs-horizontal-third">Half-style, please.</span>
    </p>
    <p>
        <span class="textToHalfStyle" data-halfstyle="hs-PeelingStyle">Half-style, please.</span>
    </p>
    <p style="background-color:#000;">
        <span class="textToHalfStyle" data-halfstyle="hs-KevinGranger">Half-style, please.</span>
    </p>

    (JSFiddle demo)

    #9133
    David Hoang
    Keymaster

    Yes, you can do this with only one character and only CSS:

    http://jsbin.com/rexoyice/1/

    h1 {
      display: inline-block;
      margin: 0; /* for demo snippet */
      line-height: 1em; /* for demo snippet */
      font-family: helvetica, arial, sans-serif;
      font-weight: bold;
      font-size: 300px;
      background: linear-gradient(to right, #7db9e8 50%,#1e5799 50%);
      background-clip: text;
      -webkit-text-fill-color: transparent;
    }
    <h1>X</h1>

    Visually, all the examples that use two characters (be it via JS, CSS pseudo elements, or just HTML) look fine, but note that that all adds content to the DOM which may cause accessibility–as well as text selection/cut/paste issues.

    #9130
    David Hoang
    Keymaster

    Here an ugly implementation in canvas. I tried this solution, but the results are worse than I expected, so here it is anyway.

    Canvas example

    $("div").each(function() {
      var CHARS = $(this).text().split('');
      $(this).html("");
      $.each(CHARS, function(index, char) {
        var canvas = $("<canvas />")
          .css("width", "40px")
          .css("height", "40px")
          .get(0);
        $("div").append(canvas);
        var ctx = canvas.getContext("2d");
        var gradient = ctx.createLinearGradient(0, 0, 130, 0);
        gradient.addColorStop("0", "blue");
        gradient.addColorStop("0.5", "blue");
        gradient.addColorStop("0.51", "red");
        gradient.addColorStop("1.0", "red");
        ctx.font = '130pt Calibri';
        ctx.fillStyle = gradient;
        ctx.fillText(char, 10, 130);
      });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div>Example Text</div>
    #9125
    David Hoang
    Keymaster

    A nice solution that takes advantage of the background-clip: text support: http://jsfiddle.net/sandro_paganotti/wLkVt/

    span{
       font-size: 100px;
       background: linear-gradient(to right, black, black 50%, grey 50%, grey);
       background-clip: text;
       -webkit-text-fill-color: transparent;
    }
    
    #9127
    David Hoang
    Keymaster

    Another CSS-only solution (though data-attribute is needed if you don’t want to write letter-specific CSS). This one works more across the board (Tested IE 9/10, Chrome latest & FF latest)

    span {
      position: relative;
      color: rgba(50,50,200,0.5);
    }
    
    span:before {
      content: attr(data-char);
      position: absolute;
      width: 50%;
      overflow: hidden;
      color: rgb(50,50,200);
    }
    <span data-char="X">X</span>
    #9128
    David Hoang
    Keymaster

    Enter image description here

    I just played with @Arbel’s solution:

    var textToHalfStyle = $('.textToHalfStyle').text();
    var textToHalfStyleChars = textToHalfStyle.split('');
    $('.textToHalfStyle').html('');
    $.each(textToHalfStyleChars, function(i,v){
        $('.textToHalfStyle').append('<span class="halfStyle" data-content="' + v + '">' + v + '</span>');
    });
    body{
        background-color: black;
    }
    .textToHalfStyle{
        display:block;
        margin: 200px 0 0 0;
        text-align:center;
    }
    .halfStyle {
        font-family: 'Libre Baskerville', serif;
        position:relative;
        display:inline-block;
        width:1;
        font-size:70px;
        color: black;
        overflow:hidden;
        white-space: pre;
        text-shadow: 1px 2px 0 white;
    }
    .halfStyle:before {
        display:block;
        z-index:1;
        position:absolute;
        top:0;
        width: 50%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow:hidden;
        color: white;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <span class="textToHalfStyle">Dr. Jekyll and M. Hide</span>
    #9124
    David Hoang
    Keymaster
    .halfStyle {
        position:relative;
        display:inline-block;
        font-size:68px; /* or any font size will work */
        color: rgba(0,0,0,0.8); /* or transparent, any color */
        overflow:hidden;
        white-space: pre; /* to preserve the spaces from collapsing */
        transform:rotate(4deg);
        -webkit-transform:rotate(4deg);
        text-shadow:2px 1px 3px rgba(0,0,0,0.3);
    }
    .halfStyle:before {
        display:block;
        z-index:1;
        position:absolute;
        top:-0.5px;
        left:-3px;
        width: 100%;
        content: attr(data-content); /* dynamic content for the pseudo element */
        overflow:hidden;
        color: white;
        transform:rotate(-4deg);
        -webkit-transform:rotate(-4deg);
        text-shadow:0 0 1px black;
    
    }
    

    http://experimental.samtremaine.co.uk/half-style/

    You can crowbar this code into doing all sorts of interesting things – this is just one implementation my associate and I came up with last night.

    #9120
    David Hoang
    Keymaster

    You can also do it using SVG, if you wish:

    var title = document.querySelector('h1'),
        text = title.innerHTML,
        svgTemplate = document.querySelector('svg'),
        charStyle = svgTemplate.querySelector('#text');
    
    svgTemplate.style.display = 'block';
    
    var space = 0;
    
    for (var i = 0; i < text.length; i++) {
      var x = charStyle.cloneNode();
      x.textContent = text[i];
      svgTemplate.appendChild(x);
      x.setAttribute('x', space);
      space += x.clientWidth || 15;
    }
    
    title.innerHTML = '';
    title.appendChild(svgTemplate);
    <svg style="display: none; height: 100px; width: 100%" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
        <defs id="FooDefs">
            <linearGradient id="MyGradient" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="50%" stop-color="blue" />
                <stop offset="50%" stop-color="red" />
            </linearGradient>
        </defs>
        <text y="50%" id="text" style="font-size: 72px; fill: url(#MyGradient)"></text>
    </svg>
    
    <h1>This is not a solution X</h1>

    http://codepen.io/nicbell/pen/jGcbq

    #9122
    David Hoang
    Keymaster

    FWIW, here’s my take on this doing it only with CSS: http://codepen.io/ricardozea/pen/uFbts/

    Several notes:

    • The main reason I did this was to test myself and see if I was able to accomplish styling half of a character while actually providing a meaningful answer to the OP.

    • I am aware that this is not an ideal or the most scalable solution and the solutions proposed by the people here are far better for “real world” scenarios.

    • The CSS code I created is based on the first thoughts that came to my mind and my own personal approach to the problem.

    • My solution only works on symmetrical characters, like X, A, O, M. **It does not work on asymmetric characters like B, C, F, K or lower case letters.

    • ** HOWEVER, this approach creates very interesting ‘shapes’ with asymmetric characters. Try changing the X to a K or to a lower case letter like an h or a p in the CSS 🙂

    HTML

    <span class="half-letter"></span>
    

    SCSS

    .half-character { 
      display: inline-block;
      font: bold 350px/.8 Arial;
      position: relative;
    
      &:before, &:after {
        content: 'X'; //Change character here
        display: inline-block;
        width: 50%;
        overflow: hidden;
        color: #7db9e8;
      }
      &:after {
        position: absolute;
        top: 0;
        left: 50%;
        color: #1e5799;
        transform: rotateY(-180deg);
      }
    }
    
    #9131
    David Hoang
    Keymaster

    If you are interested in this, then Lucas Bebber’s Glitch is a very similar and super cool effect:

    enter image description here

    Created using a simple SASS Mixin such as

    .example-one {
      font-size: 100px;
      @include textGlitch("example-one", 17, white, black, red, blue, 450, 115);
    }
    

    More details at Chris Coyer’s CSS Tricks and Lucas Bebber’s Codepen page

Viewing 15 posts - 1 through 15 (of 21 total)
  • You must be logged in to reply to this topic.