Ever dreamed of a better alternative to current web tools? You've come to the right place!

AXR is a new platform for creating web sites and applications, redesigned from the ground up to enable modern user experiences. The web you love, but better.

read the manifesto Learn more
Featured presentation

Get an early sneak-peek:

Our prototype is already capable of doing many of the cool features of HSS. It's not a full browser yet, but it allows you to start experimenting right now with the web language of the future.



Instead of writing longer and longer selector chains, the rules (the selectors + the block with the properties) can be nested inside each other. If the content in the XML file is a tree of elements, why not apply styles using a tree as well? It is both clearer and has better performance, since not all elements have to be matched against each selector.

CSS:

books { }
books > book { }
books > book > cover { }

HSS:

books {
	book {
		cover { }
	}
}

Instead of dealing with an ever growing, plain list of properties, in HSS you use objects that encapsulate a group of related values, just as objects encapsulate related functionality in traditional object oriented programming languages.

CSS:

selector
{
	border-size: 1px;
	border-color: #F00;
	border-style: solid;
}

HSS:

selector
{
	border: @stroke {
		size: 1;
		color: #F00;
		style: solid;
	};
}

You can give any HSS object a name, and reuse it as needed. You can make "presets" and apply them to the selected object(s) and then even override any property as needed.

For example:

@linearGradient boxBg
{
	startColor: #F;
	endColor: #0;
	endY: 100%;
}

@container box
{
	width: 150;
	height: 100;
	background: boxBg;
}

selector chain
{
	isA: box;
}

Anywhere a number is accepted as a value, you can also use an expression. This is especially useful when you want to mix fixed-width elements with fluid ones. For example, when you have a sidebar 150 point wide, how wide is the rest? Answer: 100% - 150.

For example:

sidebar
{
	width: 150;
}

content
{
	width: 100% - 150;
}

Functions like min(), max() or round() help you control the dimensions of your elements in fluid environments, without the need for countless properties such as min-width or max-height in CSS. The function will always return the appropriate value depending on the parameters.

For example:

selector
{
	// make it 20% the width of the parent, but at
	// least 150 points wide and at most 400 points
	width: min(150, max(400, 20%));
}

Many times it is very useful to be able to refer to a property of another element to do some calculations, for example. Imagine a site with a sidebar and content area, for example. You want to make the content area as wide as the whole page minus the sidebar, which is flexible. So you'd do something like this:

page
{
	sidebar
	{
		// like in the previous example
		width: min(150, max(400, 20%));
	}

	content
	{
		width: 100% - ref(width of sidebar);
	}
}

Filters are like pseudo-selectors in CSS but with a completely overhauled selection system. Since HSS has scope, the selectors are read from left to right. You select elements based on the name, for example, and then you filter that selection down to the elements you really want. There are a lot of them to cover all the different needs, so check out the docs.

// selects the first of the elements named foo
foo:first { }
// selects the elements named foo that are first inside
// their parent
foo:firstChild { }
// selects bar elements, then return the 2nd, 4th, 6th, etc
bar:even { }
// selects baz elements whose width is greater than 500
baz:(width > 500) { }
// selects qux elements whose title attribute start
// with "Welcome"
qux:[title:startsWith("Welcome")] { }

The structure of the content is intrinsic to its meaning, it should NEVER be altered just because of some stylistic requirements. Therefore, in HSS you can freely manipulate the content tree to fit whatever structure you need to achieve your visual layout.

root
{
	// wrap the element called "navigation" in a new
	// "header" element
	#wrap(navigation) header
	{
		// supposing myMenuPreset has been defined elsewhere
		navigation { isA: myMenuPreset; }
	}
	// wrap everything that is not "header" or "footer" in a
	// new "content" element
	#wrap(!(header, footer)) content
	{
		// change the order of the items
		#move element2 { /*etc*/ }
		#move element1 { /*etc*/ }
		#move element3 { /*etc*/ }
	}
	// create a new footer, if not already there
	#ensure footer
	{
		// create a new search box, assuming the object has been
		// defined elsewhere
		#new search { isA: searchBox; }
	}
}

A new box model, combined with most of the other features in this list, provide an awesome new way of doing layout, more suited to how designers think. Instead of floating, pushing and otherwise bang your head against the wall when laying out your elements on the page, you use alignX and alignY to set alignment points. These will determine the position of the elements in the page, which will flow inside of their parents, balancing themselves out when more than one tries to align itself on that specific point. It sounds more complicated than it really is, so here come some examples:

// align foo to the right horizontally
foo { alignX: right; }
// vertically center bar
bar { alignY: center; }
// place baz with it's right edge 30 points to the left
// of the center of its parent, without affecting other
// elements
baz
{
	anchorX: 100%;
	alignX: 50% - 30;
	flow: no;
}
// vertically center all elements *inside* qux,
// and lay them out from top to bottom instead of left
// to right
qux
{
	contentAlignY: center;
	direction: ttb;
}