使用CSS3插入border-radius

时间:2012-06-14 13:01:49

标签: css css3 css-shapes

有没有办法用css3创建插入边框半径? (没有图像)

我需要像这样的边界半径:

Inset border radius

8 个答案:

答案 0 :(得分:32)

我发现使用所有CSS和HTML(没有图像等)来实现这一目标的最好方法是using CSS3 gradients,每个Lea Verou。从她的解决方案:

div.round {
    background:
        -moz-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background:
         -o-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -o-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -o-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -o-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background:
         -webkit-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -webkit-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -webkit-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
         -webkit-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background-position: bottom left, bottom right, top right, top left;
        -moz-background-size: 50% 50%;
        -webkit-background-size: 50% 50%;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

最终结果是一组带曲线的透明渐变。有关演示的详细信息,请参阅完整的JSFiddle,并了解它的外观。

显然,这取决于对rgbagradient的支持,因此应将其视为渐进增强,或者如果它对设计至关重要,则应为旧版浏览器提供基于图像的回退(尤其是IE,即使通过IE9也不支持gradient)。

答案 1 :(得分:11)

您可以通过使用框阴影在角落中绝对定位透明圆形元素来实现此目的。我使用了包含跨度,框阴影,边框和伪选择器的隐藏溢出div的组合。

查看我的example

这是您需要开始使用的基本HTML和CSS:



a {display:inline-block; width:250px; height:100px; background:#ccc; border:2px solid #000; position:relative; margin:10px;}

a div {position: absolute; top: 0; overflow: hidden; width: 15px; height: 100%;}
a div:after {content:''; background:#000; width:2px; height:75px; position:absolute; top:12.5px;}

a div:first-of-type {left: -14px;}
a div:first-of-type:after {left:0;}

a div:last-of-type {right: -14px;}
a div:last-of-type:after {right:0;}

a span {display:block; width:30px; height:30px; background:transparent; position:absolute; bottom:-20px; right:-20px; border:2px solid #000; border-radius:25px; box-shadow:0 0 0 60px #ccc;}

a div:first-of-type span {left:-20px;}
a div:first-of-type span:first-child {top:-20px;}
a div:first-of-type span:last-child {bottom:-20px;}

a div:last-of-type span {right:-20px;}
a div:last-of-type span:first-child {top:-20px;}
a div:last-of-type span:last-child {bottom:-20px;}

<a href="">
    <div>
        <span></span>
        <span></span>
    </div>

    <div>
        <span></span>
        <span></span>
    </div>
</a>
&#13;
&#13;
&#13;

答案 2 :(得分:5)

我不认为如果角落必须是透明的,那么如果背景是已知的,你可以在每个角落创建一个带有圆形边框的div。如果这些div的背景颜色与页面背景相同,则效果将起作用。

在此处查看我的示例http://jsfiddle.net/TdDtX/

#box {
    position: relative;
    margin: 30px;
    width: 200px;
    height: 100px;
    background: #ccc;
    border: 1px solid #333;
}

.corner {
    position: absolute;
    height: 10px;
    width: 10px;
    border: 1px solid #333;
    background-color: #fff;
}

.top-left {
    top: -1px;
    left: -1px;
    border-radius: 0 0 100% 0;
    border-width: 0 1px 1px 0;
}

.top-right {
    top: -1px;
    left: 190px;
    border-radius: 0 0 0 100%;
    border-width: 0 0 1px 1px;
}

.bottom-left {
    top: 90px;
    left: -1px;
    border-radius: 0 100% 0 0;
    border-width: 1px 1px 0 0;
}

.bottom-right {
    top: 90px;
    left: 190px;
    border-radius: 100% 0 0 0;
    border-width: 1px 0 0 1px;
}
<div id="box">
    <div class="corner top-left"></div>
    <div class="corner top-right"></div>
    <div class="corner bottom-left"></div>
    <div class="corner bottom-right"></div>
</div>

答案 3 :(得分:2)

看起来不太可能。我尝试了一个带有负值的border-radius只是为了看看会发生什么,但它没有效果。

修改

即使您将盒子拆分成较小的部分,在某些时候您仍然需要创建一个透明的嵌入角落。透明度是一个棘手的部分,可能会阻止没有图像的可能性。基本上,你必须能够渲染一个带有不透明周围bg的透明圆圈(如果可以在CSS中使用,我很想知道如何:)

如果您不需要透明度,可以采取相应措施。

答案 4 :(得分:2)

你可以用新的css3-Border-images实现这种效果(好吧,它的图像,但它可以毫无问题地扩展)。但这是相当新的,并没有得到广泛的支持(在所有体面的浏览器(带前缀),除了IE准确;))。

关于csstricks上的边框图片的精彩文章。

Browser Support

答案 5 :(得分:1)

body {
    background: #fff;
}

.div{
 position:relative;
}
.box {
background: #f7f7f7;
height: 178px;
width: 409px;
margin: 25px;
/*padding: 20px;*/
position: relative;
overflow: hidden;
border: 1px solid #ccc;
border-left: 0px;
}
.box:before {
content: "";
display: block;
background: #fff;
position: absolute;
top: -33px;
left: -263px;
width: 300px;
height: 242px;
border-radius: 300px;
border: 1px solid #ccc;
}
<div class="div">
<div class="box"></div>
</div>

</body>
</html>

示例:http://jsfiddle.net/dVmX3/

答案 6 :(得分:0)

嗯,你可以在这里利用这个小技巧来创建Inset Border Radius

然后,为了支持透明度,您可能必须在其间添加其他块。或多或少像旧的圆形图像的方式;使用透明图像为每个角落设置跨度。并跨越两侧和顶部以填补空白空间。您可以使用此技巧在CSS中执行此操作,而不是使用图像。

答案 7 :(得分:0)

import UIKit

/** 
  DatasourceController is simply a UICollectionViewController that 
allows you to quickly create list views.

 In order to render our items in your list, simply provide it with a 
Datasource object.
 */
open class DatasourceController: UICollectionViewController, 
UICollectionViewDelegateFlowLayout {

open let activityIndicatorView: UIActivityIndicatorView = {
    let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
    aiv.hidesWhenStopped = true
    aiv.color = .black
    return aiv
}()

open var datasource: Datasource? {
    didSet {
        if let cellClasses = datasource?.cellClasses() {
            for cellClass in cellClasses {
                collectionView?.register(cellClass, forCellWithReuseIdentifier: NSStringFromClass(cellClass))
            }
        }

        if let headerClasses = datasource?.headerClasses() {
            for headerClass in headerClasses {
                collectionView?.register(headerClass, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: NSStringFromClass(headerClass))
            }
        }

        if let footerClasses = datasource?.footerClasses() {
            for footerClass in footerClasses {
                collectionView?.register(footerClass, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: NSStringFromClass(footerClass))
            }
        }

        collectionView?.reloadData()
    }
}

public init() {
    super.init(collectionViewLayout: UICollectionViewFlowLayout())
}

required public init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

let defaultCellId = "lbta_defaultCellId"
let defaultFooterId = "lbta_defaultFooterId"
let defaultHeaderId = "lbta_defaultHeaderId"

override open func viewDidLoad() {
    super.viewDidLoad()
    collectionView?.backgroundColor = .white
    collectionView?.alwaysBounceVertical = true

    view.addSubview(activityIndicatorView)
    activityIndicatorView.anchorCenterXToSuperview()
    activityIndicatorView.anchorCenterYToSuperview()

    collectionView?.register(DefaultCell.self, forCellWithReuseIdentifier: defaultCellId)
    collectionView?.register(DefaultHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: defaultHeaderId)
    collectionView?.register(DefaultFooter.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: defaultFooterId)
}

override open func numberOfSections(in collectionView: UICollectionView) -> Int {
    return datasource?.numberOfSections() ?? 0
}

override open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return datasource?.numberOfItems(section) ?? 0
}

//need to override this otherwise size doesn't get called
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width, height: 50)
}

override open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell: DatasourceCell

    if let cls = datasource?.cellClass(indexPath) {
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
    } else if let cellClasses = datasource?.cellClasses(), cellClasses.count > indexPath.section {
        let cls = cellClasses[indexPath.section]
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
    } else if let cls = datasource?.cellClasses().first {
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
    } else {
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: defaultCellId, for: indexPath) as! DatasourceCell
    }

    cell.controller = self
    cell.datasourceItem = datasource?.item(indexPath)
    return cell
}

override open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    let reusableView: DatasourceCell

    if kind == UICollectionElementKindSectionHeader {
        if let classes = datasource?.headerClasses(), classes.count > indexPath.section {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(classes[indexPath.section]), for: indexPath) as! DatasourceCell
        } else if let cls = datasource?.headerClasses()?.first {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
        } else {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: defaultHeaderId, for: indexPath) as! DatasourceCell
        }            
        reusableView.datasourceItem = datasource?.headerItem(indexPath.section)

    } else {
        if let classes = datasource?.footerClasses(), classes.count > indexPath.section {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(classes[indexPath.section]), for: indexPath) as! DatasourceCell
        } else if let cls = datasource?.footerClasses()?.first {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
        } else {
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: defaultFooterId, for: indexPath) as! DatasourceCell
        }
        reusableView.datasourceItem = datasource?.footerItem(indexPath.section)
    }

    reusableView.controller = self

    return reusableView
}

open func getRefreshControl() -> UIRefreshControl {
    let rc = UIRefreshControl()
    rc.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
    return rc
}

@objc open func handleRefresh() {

}

open var layout: UICollectionViewFlowLayout? {
    get {
        return collectionViewLayout as? UICollectionViewFlowLayout
    }
}
import LBTAComponents

class homeView: DatasourceController {

override func viewDidLoad() {
    super.viewDidLoad()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}