Rounded corners with JavaScript
The trick of rounding corners without using images is adding a number of 1px high slices (divs) to the top and the bottom of the element. The left and right margins of these slices are computed to give the impression of rounded corners. My code only works for divs that are in a bounding box limiting their width.
The css
The code needs one extra line in the css:
.slice{height:1px;overflow:hidden}
The code
I use a new global namespace: G. Regular visitors will probably notice that I am working on the smallest Ajax library ever. This is a smaller variant of the one I am using on this site:
var G={
init:function(){for(var n in G){if(G[n].init)G[n].init()}},
d:function(a){return a||document},
get:function(a,b){return G.d(b).getElementById(a)},
tags:function(a,b){return G.d(b).getElementsByTagName(a)},
tag:function(a,b){return G.tags(a,b)[0]},
set:function(a,b){for(var o in b)a[o]=b[o];return a},
byClass:function(a,b){var o=G.tags(a),v=[],i;for(i=0;i<o.length;i++){if(o[i].className==b)v.push(o[i])};return v},
create:function(a,b,c,d){var o=G.d(d).createElement(a);G.set(o,b);G.set(o.style,c);return o},
append:function(x,a,b,c){var o=a.tagName?a:G.create(a,b,c,x.ownerDocument);x.appendChild(o);return o},
replace:function(a,b){a.parentNode.replaceChild(b,a);return a},
style:function(a){return a.currentStyle||G.d().defaultView.getComputedStyle(a,'')}
}
G.set(String.prototype,{begins:function(a){return this.indexOf(a)==0}})
window.onload=G.init
Next the code to round corners is wrapped in an object 'rounded'. The actual function to round a div is G.rounded.round(a,b), where a is the node to round and b an object defining the parameters, e.g. {radius:15,type:'top'}.
The G.rounded.init() function is executed on page load. It contains two ways how to use it: round individual elements and add behaviour to all divs which className start with 'round'. In the last case, the radius and optional top/bottom only are passed in the className itself, e.g. class="round-15-top"}.
G.rounded={
init:function(){
var m=this,o,i,p,v,q
m.round(G.get('identity'),{radius:15,type:'top'})
m.round(G.get('legal'),{radius:15,type:'bottom'})
o=G.tags('div',G.get('main'));v=[]
for(i=0;i<o.length;i++)if(o[i].className.begins('round'))v.push(o[i])
for(i=0;i<v.length;i++){q=(v[i].className+'--').split('-');m.round(v[i],{radius:q[1],type:q[2]})}
},
round:function(a,b){
var o=G.create('div'),r=b.radius,i,oc,m=Math,pr=m.pow(r,2),v={className:'slice'},vs,os=G.style(a),qq
vs={backgroundColor:os.backgroundColor,
backgroundImage:os.backgroundImage,backgroundRepeat:os.backgroundRepeat}
if(b.type!='bottom'){
for(i=r-1;i>0;i--){
vs.marginLeft=vs.marginRight=r-m.sqrt(pr-m.pow(i,2))+'px'
vs.backgroundPosition='-'+(r-m.sqrt(pr-m.pow(i,2)))+'px '+(i-r)+'px'
G.append(o,'div',v,vs)
}
a.style.backgroundPosition='0 -'+r+'px'
}
G.append(o,a.cloneNode(true))
if(b.type!='top'){
qq=a.offsetHeight+(b.type!='bottom')?r:0
for(i=1;i<r;i++){
vs.marginLeft=vs.marginRight=r-m.sqrt(pr-m.pow(i,2))+'px'
vs.backgroundPosition='-'+(r-m.sqrt(pr-m.pow(i,2)))+'px '+(qq-i)+'px'
G.append(o,'div',v,vs)
}
}
G.replace(a,o)
}
}
Known limitations
This was just a proof of concept. The code can round background images too, but only the top corners. When you add the 'rounded' behaviour using classNames, the script above does not process nested 'round' tags correctly. In general, I would not recommend this script for every day use.Star rating
Comments
To add a comment, log in or register as new user. It's free and safe.