John Main Logo

John Main

Code. Design. Hosting. Maintenance.

05
Mar '19

I spent some time messing about with Bootstrap popovers, and other similar tools but was finding that they tended to be overly complicated to use and skin, and also mostly wouldn’t allow form elements to be inside them. I found myself with a task where I was very tight on space and needed to add several textareas to my form. A popover was the obvious choice, but many relied on convoluted attributes on the trigger element or involved javascript handlers. Even more importantly most tend to destroy the popover when it is closed, which is clearly no use I want a form element in there.

After a bit of playing around I came up with this script myself:

CSS:

.popover-container {
    position: relative;
}

.popover-content {
    z-index: 10000;
    border: 1px solid #555555;
    padding: 8px;
    margin-top: 10px;
    width: 300px;
    position: absolute;
    left: -1000000px;
}

.popover-content.open {
    left: -150px;
}

.popover-content.open:after {
    content: '';
    display: block;
    position: absolute;
    top: -6px;
    left: 150px;
    width: 10px;
    height: 10px;
    background: #FFFFFF;
    border-right:1px solid #555555;
    border-top:1px solid #555555;
    -moz-transform:rotate(-45deg);
    -webkit-transform:rotate(-45deg);
}

JS:

$().ready(function() {

    $('.popover-container').on('click', 'button', function() {
        var parent = $(this).parents('.popover-container');
        var content = parent.find('.popover-content');

        if(content.hasClass('open')) {
            closePopover(content);
        }
        else {
            //Clear down any others first
            $('.popover-content.open').each(function() {
                closePopover($this);
            });

            content.addClass('open');

            var offset = 150 - (parent.width() / 2) - 2;

            content.css('left', '-' + offset + 'px');
        }
    });

    //Close on blur
    $('.popover-container').on('blur', '.popover-content', function() {
        closePopover($(this));
    });

    //Close on escape key
    $(document).keyup(function(e) {
        if (e.keyCode === 27) {
            $('.popover-content.open').each(function() {
                closePopover($(this));
            });
        }
    });
});

function closePopover(element) {
    element.removeClass('open');
    element.css('left', '');
}

Example HTML:

<div class="popover-container">

    <button type="button" class="btn btn-xs btn-default">
        Show Popover
    </button>

    <div class="popover-content">
        <div class="form-group">
            <p>This is my popover</p>
            <textarea name="my-textarea"></textarea>
        </div>
    </div>
</div>

Note that the CSS and JS above are based around the popover being 300px wide. You can change this to whatever you like, but bear in mind that the centering (the 150px offsets) needs to be adjusted in a corresponding way.

01
Mar '15

This will be a very short post but I’ve just discovered my favourite feature of CSS3 and I wanted to share in case any of you out there missed it. Ever find yourself with elements that, if populated, work really well in the page and give a lovely user experience but, if empty, just leave gaping holes in the page. I particularly get this situation with message bars in page headers, or in labels I create ready to receive validation error messages.

Now I know the true CSS ninjas will have a million and one ways to deal with this, but by far the simplest and most excellent approach I’ve found is the CSS3 :empty selector:

label.error:empty {
   display: none;
}

Just like that! Any empty labels with the ‘error’ class will be hidden. As soon as they are populated they will show. Easy.
It’s worth noting though that even a single space within the element will cause it to be viewed as not empty – be careful with your whitespace out there!

<Insert note about CSS3 not being supported by all browsers here>

15
May '12

It amazes me how many people online are saying that CSS won’t natively support columns of data using lists. Everything from tables to Javascript functions are being suggested but it’s actually very very simple to do. To make the LI elements within and OL or UL list arrange themselves into two equal columns all you need to do is this:

li {
    float: left;
    width: 50%;
}

Equally to arrange themselves into three columns you just need to adjust the width value like so:

li {
    float: left;
    width: 33.3%;
}

I’m sure you’re getting the idea!