diff --git a/examples/custom-icon.html b/examples/custom-icon.html
new file mode 100644
index 0000000000..e4fa79f342
--- /dev/null
+++ b/examples/custom-icon.html
@@ -0,0 +1,9 @@
+---
+layout: example.html
+title: Custom Icon
+shortdesc: Example using a custom attribution icon object
+docs: >
+ This example creates a custom element for the attribution icon
+tags: "icon, element"
+---
+
diff --git a/examples/custom-icon.js b/examples/custom-icon.js
new file mode 100644
index 0000000000..a5377ea484
--- /dev/null
+++ b/examples/custom-icon.js
@@ -0,0 +1,27 @@
+goog.require('ol.Map');
+goog.require('ol.View');
+goog.require('ol.layer.Tile');
+goog.require('ol.source.OSM');
+
+var logoElement = document.createElement('a');
+logoElement.href = 'http://www.osgeo.org/';
+logoElement.target = '_blank';
+
+var logoImage = new Image();
+logoImage.src = 'http://www.osgeo.org/sites/all/themes/osgeo/logo.png';
+
+logoElement.appendChild(logoImage);
+
+var map = new ol.Map({
+ layers: [
+ new ol.layer.Tile({
+ source: new ol.source.OSM()
+ })
+ ],
+ target: 'map',
+ view: new ol.View({
+ center: [0, 0],
+ zoom: 2
+ }),
+ logo: logoElement
+});
diff --git a/externs/olx.js b/externs/olx.js
index c3fec4bade..4356955511 100644
--- a/externs/olx.js
+++ b/externs/olx.js
@@ -175,7 +175,7 @@ olx.interaction.InteractionOptions.prototype.handleEvent;
* layers: (Array.|ol.Collection.|undefined),
* loadTilesWhileAnimating: (boolean|undefined),
* loadTilesWhileInteracting: (boolean|undefined),
- * logo: (boolean|string|olx.LogoOptions|undefined),
+ * logo: (boolean|string|olx.LogoOptions|Element|undefined),
* overlays: (ol.Collection.|Array.|undefined),
* renderer: (ol.RendererType|Array.|string|undefined),
* target: (Element|string|undefined),
@@ -261,9 +261,10 @@ olx.MapOptions.prototype.loadTilesWhileInteracting;
* The map logo. A logo to be displayed on the map at all times. If a string is
* provided, it will be set as the image source of the logo. If an object is
* provided, the `src` property should be the URL for an image and the `href`
- * property should be a URL for creating a link. To disable the map logo, set
- * the option to `false`. By default, the OpenLayers 3 logo is shown.
- * @type {boolean|string|olx.LogoOptions|undefined}
+ * property should be a URL for creating a link. If an element is provided,
+ * the element will be used. To disable the map logo, set the option to
+ * `false`. By default, the OpenLayers 3 logo is shown.
+ * @type {boolean|string|olx.LogoOptions|Element|undefined}
* @api stable
*/
olx.MapOptions.prototype.logo;
diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js
index 3664842c21..82ff344789 100644
--- a/src/ol/control/attributioncontrol.js
+++ b/src/ol/control/attributioncontrol.js
@@ -309,6 +309,9 @@ ol.control.Attribution.prototype.insertLogos_ = function(frameState) {
var logoValue = logos[logoKey];
if (logoValue === '') {
logoElement = image;
+ } else if (goog.dom.isElement(logoValue)) {
+ goog.asserts.assertElement(logoValue);
+ logoElement = logoValue;
} else {
logoElement = goog.dom.createDom('A', {
'href': logoValue
diff --git a/src/ol/map.js b/src/ol/map.js
index 8f48fb8dc7..4428fe1350 100644
--- a/src/ol/map.js
+++ b/src/ol/map.js
@@ -1450,7 +1450,7 @@ ol.Map.prototype.unskipFeature = function(feature) {
* @typedef {{controls: ol.Collection.,
* interactions: ol.Collection.,
* keyboardEventTarget: (Element|Document),
- * logos: Object.,
+ * logos: (Object.),
* overlays: ol.Collection.,
* rendererConstructor:
* function(new: ol.renderer.Map, Element, ol.Map),
@@ -1490,6 +1490,8 @@ ol.Map.createOptionsInternal = function(options) {
var logo = options.logo;
if (typeof logo === 'string') {
logos[logo] = '';
+ } else if (goog.dom.isElement(logo)) {
+ logos['logo'] = logo;
} else if (goog.isObject(logo)) {
goog.asserts.assertString(logo.href, 'logo.href should be a string');
goog.asserts.assertString(logo.src, 'logo.src should be a string');