Typeoneerror Featured in Rangefinder Magazine

Rangefinder

We were honored this week to have a write-up Rangefinder Magazine in Danielle Currier's How-to Article on Optimizing Your Online Portfolio. In the article, Typeoneerror's Ben Borowski talks about using responsive web design methods to create experiences that scale across multiple desktop and mobile platforms. Our website for photographer Noah Webb is highlighted in the "How-To" issue. You can check out the spread here on the Rangefinder website or download a PDF version from our own site here.

September 14th, 2012 | Permalink

T1E is hiring

studio

Typeoneerror is growing and I am looking for a select group of creative individuals who will form our core product-development team over the next year and assist with various client projects on a daily basis. I am searching for unique talents with experience in the development and design of interactive applications and games on multiple platforms.

I typically work with small teams of independent contractors on our projects, but reached a point where having people in the office makes sense. That's where you come in, I hope!


Roles

At this time, I am looking to hire a developer in the junior- to mid-level range, as well as a (paid) intern. Candidates should have front-end development experience as well as some experience with programming languages.


Requirements

  • HTML(5)
  • CSS(3)
  • Javascript(jQuery, OK)
  • Ability to translate PSD and FW templates to clean, responsive code
  • Experience with front-end PHP or Ruby development

A solid foundation in the basic web development technologies listed above are required for this position, and experience with PHP would be fantastic, but here's a list of some of the technologies I am currently working on that, if you had experience with, would certainly tip the scales in your favor:


Niceties

  • SmartyPHP
  • Understanding of version control (subversion, git)
  • Wordpress
  • Flash/Flex/AIR APIs
  • LAMP development
  • Rails/Ruby development
  • Experience with OOP & MVC frameworks (Zend, Rails, Django, CakePHP)
  • Objective-C (iOS apps)
  • Java (Android apps)
  • Facebook apps
  • Database design
  • Information architecture
  • Game Development (iOS, Android, XNA)
  • Familiarity with *nix, Apache
  • Front-end asset pipelines (sass, less, compass, haml)

Also required are positive attitudes and strong opinions about the web.


How to Apply

Candidates should feel free to submit a cover letter and resume (or relevant URL) with applicable work samples and salary requirements to hello@typeoneerror.com. Click the mailto links below to start:

Junior Developer
Intern

Thanks for reading, and feel free to tweet about this if you'd like to help me out.


About Typeoneerror

Located in the Ballard neighborhood of Seattle, Typeoneerror is an interactive design boutique led by artist and programmer Benjamin Borowski; committed to creating fine interactive applications via direct and collaborative engagements. Providing strategic design and development for websites, games, and mobile devices, our core expertise melds hand-crafted code with beautiful, user-centric design & strategy.

November 22nd, 2011 | Permalink

Reducing CSS/Javascript Requests and File Size with Ant and YUI

With continuing reliance on front-end Javascript plugins and CSS, it's important to keep HTTP requests and file sizes smaller to reduce page load times. On this site, we use jQuery, jQuery Address, a custom application Javascript include, and other plugins. We also use a master CSS file as well as a reset file and other CSS additions for things like @media queries and the like. We can reduce all these file requests to one or two requests by combining them all into one file and minifying them.

We can use a compression tool such as YUI Compressor to handle the minifying, but actually doing the work to compile all those files together and run them through the compressor can be a time-consuming task to perform manually. It'd be great if we had a tool to do that for us. Enter Apache Ant.

Ant is a java-based build automation tool. It can be used to perform a variety of tasks and is ideally suited for building files for web applications. If you're on Mac OS X, Ant comes pre-installed (1.7.x on 10.5 and 1.8.x on 10.6). For other systems, check out the easy instructions here. YUI is a simple download and extraction from here.

All we need for a basic Ant task is a build file. Create a "build.xml" file in the root of your application. To start, you just need some basic markup. I added a property that contains the path to the YUI Compressor .jar file.

<?xml version="1.0" encoding="UTF-8"?>

<!-- project name, default target and base directory -->
<project name="typeoneerror" default="init" basedir=".">

    <!-- path to YUI Compressor -->
    <property name="yuic" location="/Users/typeoneerror/bin/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar"/>

    <!-- path to build resources -->
    <property name="css" location="public/css"/>
    <property name="js" location="public/js"/>
    <property name="ui_css" location="public/ui/css"/>
    <property name="ui_js" location="public/ui/js"/>

    <!-- default target -->
    <target name="init"/>
</project>

This defines our project build with a default target (one of the actions that will run when we build) called "init". Also, we've defined some properties (paths to YUI and to our CSS and Javascript folder) that we'll use later.

Next, create the first target:

<!--concatenate javascript-->
<target name="concat.js" description="Stick all the JS together">
     <concat destfile="build/application.js">
        <!-- first concat all the files in the /ui/js directory -->
        <filelist dir="${ui_js}" files="jquery.min.js,jquery.address.min.js"/>
        <!-- then add our application js file -->
        <filelist dir="${js}" files="application.js"/>
    </concat>
</target>

This target uses the concat process to concatenate a list of javascript files into a destfile (destination file) build/application.js. This combines everything we're using into one file. The next target will use that file and minify it:

<!--minify javascript-->
<target name="minify.js" depends="concat.js" description="Minify JavaScript using YUI Compressor">
    <apply executable="java" parallel="false">
        <!-- look for any javascript files in the build dir -->
        <fileset dir="build" includes="*.js"/>
        <!-- pass arguments to the yui program -->
        <arg line="-jar"/>
        <arg path="${yuic}"/>
        <srcfile/>
        <!-- output minified files to our js dir with .min.js extenstion -->
        <arg line="-o"/>
        <mapper type="glob" from="*.js" to="${js}/*.min.js"/>
        <targetfile/>
    </apply>
</target>

The depends property defines actions that need to be performed before running the target. Add the minify.js target to the depends property of our default action:

<target name="init" depends="minify.js"/>

When we run the build, init will be run and then minify.js. Of course, concat.js will be run before minify.js since minify.js depends on it.

We add another two targets to concat and minify our CSS. Add another target to the list of targets in the init target. Our final build file looks something like this:

<?xml version="1.0" encoding="UTF-8"?>

<!-- project name, default target and base directory -->
<project name="typeoneerror" default="init" basedir=".">

    <!-- path to YUI Compressor -->
    <property name="yuic" location="/Users/typeoneerror/bin/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar"/>

    <!-- path to build resources -->
    <property name="css" location="public/css"/>
    <property name="js" location="public/js"/>
    <property name="ui_css" location="public/ui/css"/>
    <property name="ui_js" location="public/ui/js"/>

    <!-- default target -->
    <target name="init" depends="minify.js,minify.css"/>

    <!--concatenate javascript-->
    <target name="concat.js" description="Stick all the JS together">
         <concat destfile="build/application.js">
            <!-- first concat all the files in the /ui/js directory -->
            <filelist dir="${ui_js}" files="jquery.min.js,jquery.address.min.js"/>
            <!-- then add our application js file -->
            <filelist dir="${js}" files="application.js"/>
        </concat>
    </target>

    <!--minify javascript-->
    <target name="minify.js" depends="concat.js" description="Minify JavaScript using YUI Compressor">
        <apply executable="java" parallel="false">
            <!-- look for any javascript files in the build dir -->
            <fileset dir="build" includes="*.js"/>
            <!-- pass arguments to the yui program -->
            <arg line="-jar"/>
            <arg path="${yuic}"/>
            <srcfile/>
            <!-- output minified files to our js dir with .min.js extenstion -->
            <arg line="-o"/>
            <mapper type="glob" from="*.js" to="${js}/*.min.js"/>
            <targetfile/>
        </apply>
    </target>

    <!--concatenate css-->
    <target name="concat.css" description="Stick all the CSS together">
         <concat destfile="build/core.css">
            <filelist dir="${ui_css}" files="reset.min.css"/>
            <filelist dir="${css}" files="screen.css,additions.css"/>
        </concat>
    </target>

    <!--minify concatenated css-->
    <target name="minify.css" depends="concat.css" description="Minify CSS using YUI Compressor">
        <apply executable="java" parallel="false">
            <fileset dir="build" includes="*.css"/>
            <arg line="-jar"/>
            <arg path="${yuic}"/>
            <srcfile/>
            <arg line="-o"/>
            <mapper type="glob" from="*.css" to="${css}/*.min.css"/>
            <targetfile/>
        </apply>
    </target>
</project>

Running an Ant build file is as simple as shelling into the directory via your Terminal or command line interface and entering ant. It automatically looks for a file called "build.xml". You can also grab Simon Gregory's Ant TextMate Bundle if you want to just hit Cmd+R to build in your TextMate project (awesome).

December 20th, 2010 | Permalink

HTML5 & CSS3: Graceful Degradation

Webkit animations and transitions are a nifty way to add sexy effects and animations to browsers that use the webkit engine. As the list of browsers that implement these becomes longer (Safari, Chrome, Mobile Safari, Blackberry 6.0, Android, webOS, et al)—especially in the mobile space—the more you can rationalize using some of these features in production. The key words for things like this are "graceful degradation" i.e., use it, but provide a fallback solution for other browsers that will still engage the user. The idea is for the user to not think that something is missing or broken—they are still provided an engaging experience.

An example of this we created recently is a mobile-optimized HTML5 site for First Bank. At the moment it's a place to download free books in PDF form. We'll be adding more activities soon ;) On the books page, though, we use @webkit-keyframes to create a 3D transition effect when changing pages and a Mac-style "bouncing icon in the dock" effect when a book is clicked (try it in Chrome or Safari). In other browsers (Firefox, IE, etc), Javascript is used to create a simple tween animation to show the next page of books. So we give "fancy-ass" browsers some cool effects, but still give the average crowd a nice animation as well.

Here's how we created the Mac icon dock bounce. First, you define a series of keyframes that will define our animation. This is just in your CSS file—I know it looks kind of crazy when you're thinking CSS:

@-webkit-keyframes book-active {
    from {top:0px;}
    to {top:-10px;}
}

Pretty simply, we've defined an "animation name" called book-active. This animation would move whatever element it is applied to from 0 to -10. To run the animation, create a class with a similar name (I find it helps organize) and add the animation-name to it:

.book-active {
     -webkit-animation-name:book-active;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

You can see above we gave it an "animation-name" of "book-active". The animation will take 0.2 seconds to complete and it'll repeat the animation 10 times. The animation-direction parameter tells it to reverse the animation for each interaction. Hence, we bounce.

To apply the animation, you simply add the class to the element:

<article class="book-active"></article>

On the First Bank micro-site, we applied two separate bounce animations to the books. One to bounce the book element, and one to scale the shadow underneath the book on the same bounce to give it some depth. Here's the whole CSS section for the book bounce, shadow, and the 3D transform during the page change animation:

@-webkit-keyframes book-active {
    from {top:0px;}
    to {top:-10px;}
}

@-webkit-keyframes shadow-bounce {
    from {-webkit-transform:scale(1.0);}
    to {-webkit-transform:scale(1.05);}
}

@-webkit-keyframes book-transition {
    from {
        -webkit-transform:scale(1.0);
        -webkit-animation-timing-function:ease-out;
    }
    20% {
        -webkit-transform:scale(0.9);
        webkit-animation-timing-function:ease-in;
    }
    to {
        -webkit-transform:scale(1.0);
        -webkit-animation-timing-function:ease-out;
    }
}

.book-active {
     -webkit-animation-name:book-active;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

.book-transition {
    -webkit-animation-name:book-transition;
    -webkit-animation-duration:1s;
    -webkit-animation-iteration-count:1;
}

.shadow-bounce {
     -webkit-animation-name:shadow-bounce;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

One caveat for animation with webkit, is that repeating animations is tricky. Once the class has been added, you need to remove the animation-name from the element to restart the animation. We created this simple jQuery element function to help:

$.fn.startWebkitAnimation = function(name)
{
    var element = $(this);
    if (!element.hasClass(name))
    {
        element.addClass(name);
    }
    else
    {
        element.css("-webkit-animation-name", "none");
        setTimeout(function() {
            element.css("-webkit-animation-name", name);
        }, 0);
    }
    return $(this);
}

So to start an animation, simply call $("selector").startWebkitAnimation("animation-name"). The CSS class and the keyframes should have the same name. What this does is clear the animation-name property and then reset it. This is based on Apple's own recommendation for resetting animations.

On First Bank Free, we use Modernizr to check if CSS Animations are available. If they are, we start the bouncing animation when the book is clicked and delay the transition to the link. Otherwise, we go right to the link (graceful degradation!):

$("#book-list li a").click(function(event)
{
    if ($(this).data("was-clicked") != undefined)
    {
        // prevent multiple clicks
        event.preventDefault();
        return;
    }
    if (Modernizr.cssanimations)
    {
        event.preventDefault();
        // prevent multiple clicks
        $(this).data("was-clicked", 1);
        // start the book bouncing
        $(this).startWebkitAnimation("book-active");
        // start the shadow bouncing
        $(this).parent().find(".book-shadow").startWebkitAnimation("shadow-bounce");
        // delay the page direction for a tick
        setTimeout('window.location = "' + $(this).attr("href") + '"', 1000);
    }
});

So, you can see how HART (HTML5 and Related Technologies) can be used right now with a little extra effort. The keys are fallbacks and degradation. Also—and I find this to be critical—definitely let your clients know up front what to expect for different browser vendors. This might be defined in functional specification or proposal before development begins.

October 2nd, 2010 | Permalink

Simple Rounded Buttons in Opera with SVG-infused CSS

One of the important considerations of the new typeoneerror.com was that I'd not care as much cross-browser rendering issues or, more pointedly, "how things look in IE." That being said, I used many fun CSS3-style techniques such as border-radius:

-moz-border-radius:8px;
-webkit-border-radius:8px;

Safari (and Google Chrome, being both based on Webkit) and Firefox render my buttons and highlighted navigation buttons with rounded edges beautifully, and the rest of you get squares – it degrades pretty nicely. I did want to know whether Opera had any support for these "hacks." I'd heard of -opera-border-radius and -o-border-radius but they didn't work for me. The latest alpha version of Opera has full support for border-radius, but here's how you can achieve the exact same effect using simple SVG and pointing to those files in your CSS.

Our goal is to approximate the look created by our navigation button in browsers that support border-radius:

/* part of our navigation button definition **/
#nav ul li a {
    background-color:#03FFC1;
    border-radius:8px;          /* CSS3 */
    -khtml-border-radius:8px;   /* Some linux-based browsers */
    -moz-border-radius:8px;     /* Firefox > 3.1 */
    -webkit-border-radius:8px;  /* Safari */
}

Using XML-defined SVG, you can define a shape that you can use as a background image in CSS. Here, for example, is the definition of an SVG shape for the highlighted navigation button. Here's what the file I created (nav.svg) looks like:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
    <rect x="0" y="0" rx="8" ry="8" height="100%" width="100%" fill="#03FFC1" />
</svg>

Quite simply, this defines a rectangle that will scale (width/height 100%) to fill our background and has a corner radius (rx/ry) of 8. Now if I wanted to apply this to my nav buttons above:

/* use css "hacks" to target opera */
@media all and (-webkit-min-device-pixel-ratio:10000),not all and (-webkit-min-device-pixel-ratio:0){
    #nav ul li a {
        background:url(../img/nav.svg);
    }
}

You simply have to point the background of the element to the svg file just like you would an image. Won't be long now until all major browsers support border-radius; won't that be nice. I also looked in to getting something going for Internet Explorer and found this behavior script for IE that works really well. I'd only recommend it if you only have a few elements that need round edges. On the pages where I have a lot of buttons that have round corners, it took up to 10 seconds to process. Interesting idea though.

December 21st, 2009 | Permalink