diff --git a/lib/editor/widgets/Iframe/index.js b/lib/editor/widgets/Iframe/index.js
index 53af98d3a2a5a60cb39b4b179bba20b80924deec..0234d68198f4163df74b1280bfb123138a39e695 100644
--- a/lib/editor/widgets/Iframe/index.js
+++ b/lib/editor/widgets/Iframe/index.js
@@ -47,6 +47,7 @@ var Iframe = function (_a) {
   }
 
   var manualMaxWidthSet = typeof data.maxWidth !== 'undefined';
+  var manualHeightSet = typeof data.height !== 'undefined';
 
   function handleChangeManualMaxWidth(e) {
     var newValue = e.target.checked;
@@ -55,6 +56,7 @@ var Iframe = function (_a) {
 
     if (newValue) {
       update.maxWidth = 200;
+      delete update.ratio;
     } else {
       delete update.maxWidth;
     }
@@ -62,12 +64,69 @@ var Iframe = function (_a) {
     onChange(update);
   }
 
+  function handleChangeManualHeight(e) {
+    var newValue = e.target.checked;
+
+    var update = tslib_1.__assign({}, data);
+
+    if (newValue) {
+      update.height = 200;
+      delete update.ratio;
+    } else {
+      delete update.height;
+    }
+
+    onChange(update);
+  }
+
+  var parseIframe = function (e) {
+    var value = e.target.value;
+
+    if (value.startsWith('<iframe ')) {
+      var div = document.createElement('div');
+      div.innerHTML = value.trim();
+      var elements = div.getElementsByTagName('iframe');
+      var iframe = Array.from(elements)[0];
+      var srcValue = iframe.getAttribute('src');
+      var widthValue = iframe.getAttribute('width');
+      var heightValue = iframe.getAttribute('height');
+      var newData = {};
+
+      if (srcValue) {
+        newData.src = srcValue;
+      }
+
+      if (widthValue && !isNaN(Number(widthValue)) && heightValue && !isNaN(Number(heightValue))) {
+        newData.ratio = Number(parseFloat(String(Number(widthValue) / Number(heightValue))).toFixed(2));
+        delete data.maxWidth;
+        delete data.height;
+      } else if (widthValue && !isNaN(Number(widthValue)) && (!heightValue || isNaN(Number(heightValue)))) {
+        newData.maxWidth = Number(widthValue);
+        delete data.ratio;
+        delete data.height;
+      } else if (height && !isNaN(Number(height)) && (!widthValue || isNaN(Number(widthValue)))) {
+        newData.height = Number(heightValue);
+        delete data.ratio;
+        delete data.maxWidth;
+      }
+
+      onChange(tslib_1.__assign(tslib_1.__assign({}, data), newData));
+    }
+  };
+
   var src = data.src || '';
+  var ratio = data.ratio;
   var maxWidth = data.maxWidth;
   var height = (_b = data.height) !== null && _b !== void 0 ? _b : Iframe_1.DEFAULT_HEIGHT;
   return React.createElement(React.Fragment, null, React.createElement(Message_1["default"], {
     warning: true
   }, "Vsadzovanie obsahu tret\u00EDch str\u00E1n m\u00F4\u017Ee priamo ohrozi\u0165 bezpe\u010Dnos\u0165 v\u00E1\u0161ho webu.", React.createElement("br", null), "Uistite sa, \u017Ee URL je spr\u00E1vna a zobrazuje sa o\u010Dak\u00E1van\u00FD obsah."), React.createElement(FormField_1["default"], {
+    rows: 4,
+    placeholder: 'Napr. <iframe width="665" height="500" src="https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032" />',
+    onChange: parseIframe,
+    type: "textarea",
+    label: "Z\u00EDska\u0165 z iframe tagu"
+  }), React.createElement(FormField_1["default"], {
     label: "URL",
     name: "src",
     type: "text",
@@ -75,11 +134,24 @@ var Iframe = function (_a) {
     value: src,
     onChange: handleChangeInputValue,
     placeholder: "https://"
+  }), React.createElement(FormField_1["default"], {
+    onChange: handleChangeManualHeight,
+    label: "Manu\u00E1lne nastavi\u0165 v\u00FD\u0161ku",
+    type: "checkbox",
+    checked: manualHeightSet
   }), React.createElement(FormField_1["default"], {
     onChange: handleChangeManualMaxWidth,
     label: "Manu\u00E1lne nastavi\u0165 maxim\u00E1lnu \u0161\u00EDrku",
     type: "checkbox",
     checked: manualMaxWidthSet
+  }), !manualHeightSet && !manualMaxWidthSet && React.createElement(FormField_1["default"], {
+    label: "Pomer str\u00E1n",
+    name: "ratio",
+    type: "number",
+    required: true,
+    value: ratio,
+    onChange: handleChangeInputValue,
+    placeholder: "\u0160\u00EDrka/v\u00FD\u0161ka, napr. 1.33"
   }), manualMaxWidthSet && React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], null, "Maxim\u00E1lna \u0161\u00EDrka v pixeloch"), React.createElement(InputRange, {
     type: "range",
     min: 1,
@@ -92,7 +164,7 @@ var Iframe = function (_a) {
     value: maxWidth,
     name: "maxWidth",
     onChange: handleChangeNumberInputValue
-  })), React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], {
+  })), manualHeightSet && React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], {
     required: true
   }, "V\u00FD\u0161ka v pixeloch"), React.createElement(InputRange, {
     type: "range",
diff --git a/lib/editor/widgets/Table/RichTextEditor/Link.js b/lib/editor/widgets/Table/RichTextEditor/Link.js
index 64c85a9f3a980f50ed467440e12deedfafb7c97c..69f8f1a73d3d29ad6fec673e2c500c258d13ce77 100644
--- a/lib/editor/widgets/Table/RichTextEditor/Link.js
+++ b/lib/editor/widgets/Table/RichTextEditor/Link.js
@@ -5,10 +5,10 @@ exports.findLinkEntities = void 0;
 
 var tslib_1 = require("tslib");
 
-var react_1 = tslib_1.__importDefault(require("react"));
-
 var prop_types_1 = tslib_1.__importDefault(require("prop-types"));
 
+var react_1 = tslib_1.__importDefault(require("react"));
+
 function findLinkEntities(contentBlock, callback, contentState) {
   contentBlock.findEntityRanges(function (character) {
     var entityKey = character.getEntity();
diff --git a/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js b/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js
index 60e26566f866e41e3c13108044c07c4a13c0e47a..5ce9a186919125d3f0c0a9232f1f785ee242aa72 100644
--- a/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js
+++ b/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js
@@ -16,6 +16,8 @@ var react_1 = tslib_1.__importStar(require("react"));
 
 var styled_components_1 = tslib_1.__importStar(require("styled-components"));
 
+var Link_1 = tslib_1.__importStar(require("../../RichTextEditor/Link"));
+
 var elements_1 = require("./elements");
 
 var HANDLED = 'handled';
@@ -110,12 +112,17 @@ function (_super) {
     var _a = this.props,
         __editorState = _a.value.__editorState,
         active = _a.active;
+    var decorator = new draft_js_1.CompositeDecorator([{
+      strategy: Link_1.findLinkEntities,
+      component: Link_1["default"]
+    }]);
+    var editorState = draft_js_1.EditorState.createWithContent(__editorState.getCurrentContent(), decorator);
     return react_1["default"].createElement(Wrapper, {
       onClick: this.focus,
       active: active
     }, react_1["default"].createElement(draft_js_1.Editor, {
       onFocus: this.handleFocus,
-      editorState: __editorState,
+      editorState: editorState,
       handleKeyCommand: this._handleKeyCommand,
       blockStyleFn: this.blockStyleFn,
       onChange: this.handleChange,
diff --git a/lib/editor/widgets/Table/Spreadsheet/Toolbar.js b/lib/editor/widgets/Table/Spreadsheet/Toolbar.js
index 3d7e0a7e1ef8500f9716e1e5f8990f8481285ee2..3914dd80707b7b34f6dba6a4c0b41980383d5990 100644
--- a/lib/editor/widgets/Table/Spreadsheet/Toolbar.js
+++ b/lib/editor/widgets/Table/Spreadsheet/Toolbar.js
@@ -14,6 +14,10 @@ var BlockAlignTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/
 
 var InlineStyleTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/InlineStyleTool"));
 
+var LinkRemovalTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkRemovalTool"));
+
+var LinkTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkTool"));
+
 var styles_1 = require("../RichTextEditor/tools/styles");
 
 var TableHeaderTool_1 = tslib_1.__importDefault(require("./tools/TableHeaderTool"));
@@ -64,6 +68,12 @@ function (_super) {
       editorState: editorState,
       icon: "strikethrough",
       type: "STRIKETHROUGH"
+    })), react_1["default"].createElement(styles_1.ToolGroup, null, react_1["default"].createElement(LinkTool_1["default"], {
+      onToggle: onAction,
+      editorState: editorState
+    }), react_1["default"].createElement(LinkRemovalTool_1["default"], {
+      onToggle: onAction,
+      editorState: editorState
     })), react_1["default"].createElement(styles_1.ToolGroup, null, react_1["default"].createElement(BlockAlignTool_1["default"], {
       onToggle: onAction,
       editorState: editorState,
diff --git a/lib/editor/widgets/Table/Spreadsheet/index.js b/lib/editor/widgets/Table/Spreadsheet/index.js
index 6a3df4bd683412bf0772aa53e5aa5d94f058d945..487cb657d7da54946caa8c7a3cc33386acf7708f 100644
--- a/lib/editor/widgets/Table/Spreadsheet/index.js
+++ b/lib/editor/widgets/Table/Spreadsheet/index.js
@@ -15,15 +15,19 @@ var action_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/BlockAli
 
 var action_2 = tslib_1.__importDefault(require("../RichTextEditor/tools/InlineStyleTool/action"));
 
+var action_3 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkRemovalTool/action"));
+
+var action_4 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkTool/action"));
+
 var Table_1 = tslib_1.__importDefault(require("./Table"));
 
 var Toolbar_1 = tslib_1.__importDefault(require("./Toolbar"));
 
-var action_3 = tslib_1.__importDefault(require("./tools/HeaderOptionsTool/action"));
+var action_5 = tslib_1.__importDefault(require("./tools/HeaderOptionsTool/action"));
 
-var action_4 = tslib_1.__importDefault(require("./tools/TableHeaderTool/action"));
+var action_6 = tslib_1.__importDefault(require("./tools/TableHeaderTool/action"));
 
-var action_5 = tslib_1.__importDefault(require("./tools/TableSizeTool/action"));
+var action_7 = tslib_1.__importDefault(require("./tools/TableSizeTool/action"));
 
 var utilities_1 = require("./utilities");
 
@@ -51,7 +55,7 @@ function (_super) {
       table: [],
       selectedCell: []
     };
-    _this.actionHandlers = [action_1["default"], action_2["default"]];
+    _this.actionHandlers = [action_1["default"], action_2["default"], action_3["default"], action_4["default"]];
 
     _this.handleFocusCell = function (selectedCell) {
       _this.setState({
@@ -71,7 +75,7 @@ function (_super) {
       var selectedCellEditorState = table[rowIdx].cells[colIdx].__editorState;
 
       if (action.type === 'TABLE_SIZE') {
-        var _c = action_5["default"]({
+        var _c = action_7["default"]({
           table: table,
           selectedCell: selectedCell
         }, action, {
@@ -88,7 +92,7 @@ function (_super) {
           _this.propagateTableChange(_this.state.table);
         });
       } else if (action.type === 'TABLE_STRUCTURE') {
-        var _d = action_3["default"]({
+        var _d = action_5["default"]({
           table: table,
           selectedCell: selectedCell
         }, action, {
@@ -105,7 +109,7 @@ function (_super) {
           _this.propagateTableChange(_this.state.table);
         });
       } else if (action.type === 'TABLE_HEADER') {
-        onChangeHeader(action_4["default"](header, action));
+        onChangeHeader(action_6["default"](header, action));
       } else {
         _this.handleChangeCell(selectedCell, _this.actionHandlers.reduce(function (editorState, actionHandler) {
           return actionHandler(editorState, action);
diff --git a/lib/editor/widgets/Table/Spreadsheet/utilities.js b/lib/editor/widgets/Table/Spreadsheet/utilities.js
index 4ba1d03046757139213f1fde8c1b9de4b1aa74cc..78bdf2f3a7fd71585d31a8e4c8a54fc3b627fc85 100644
--- a/lib/editor/widgets/Table/Spreadsheet/utilities.js
+++ b/lib/editor/widgets/Table/Spreadsheet/utilities.js
@@ -49,6 +49,20 @@ function contentStateToHtml(contentState) {
       }
 
       return undefined;
+    },
+    entityStyleFn: function (entity) {
+      var entityType = entity.get('type').toLowerCase();
+
+      if (entityType === 'link') {
+        var data = entity.getData();
+        return {
+          element: 'a',
+          attributes: {
+            target: data.openInNewWindow ? '_blank' : '',
+            href: data.url
+          }
+        };
+      }
     }
   });
 }
diff --git a/lib/view/widgets/Iframe/index.js b/lib/view/widgets/Iframe/index.js
index e6302e9fbe142beacd37de59e9e06d2f1823a992..104b1677bb5c7a36fc091a45d5643a2a40dfd681 100644
--- a/lib/view/widgets/Iframe/index.js
+++ b/lib/view/widgets/Iframe/index.js
@@ -5,6 +5,8 @@ exports.DEFAULT_HEIGHT = void 0;
 
 var tslib_1 = require("tslib");
 
+var polished_1 = require("polished");
+
 var react_1 = tslib_1.__importDefault(require("react"));
 
 var styled_components_1 = tslib_1.__importStar(require("../../../theme/styled-components"));
@@ -12,14 +14,14 @@ var styled_components_1 = tslib_1.__importStar(require("../../../theme/styled-co
 var _utilities_1 = require("../../../utilities");
 
 exports.DEFAULT_HEIGHT = 200;
-var Wrapper = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n  display: flex;\n"], ["\n  display: flex;\n"])));
-var IframeElement = styled_components_1["default"].iframe(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n  margin: 0 auto;\n  padding: 0;\n  width: 100%;\n  border: none;\n  background: transparent;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n  ", "\n  ", "\n"], ["\n  margin: 0 auto;\n  padding: 0;\n  width: 100%;\n  border: none;\n  background: transparent;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n  ", "\n  ", "\n"])), function (_a) {
-  var maxWidth = _a.maxWidth;
-  return maxWidth && styled_components_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n      max-width: ", "px;\n    "], ["\n      max-width: ", "px;\n    "])), maxWidth);
-}, function (_a) {
-  var height = _a.height;
-  return styled_components_1.css(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n    height: ", "px;\n  "], ["\n    height: ", "px;\n  "])), height);
+var Wrapper = styled_components_1["default"]('div')(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n  position: relative;\n  display: flex;\n  width: 100%;\n  ", "\n"], ["\n  position: relative;\n  display: flex;\n  width: 100%;\n  ", "\n"])), function (_a) {
+  var hasRatio = _a.hasRatio,
+      width = _a.width,
+      height = _a.height;
+  return hasRatio ? styled_components_1.css(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n          padding-top: ", "%;\n        "], ["\n          padding-top: ", "%;\n        "])), 100 / (width / height)) : styled_components_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n          height: ", ";\n          max-width: ", ";\n        "], ["\n          height: ", ";\n          max-width: ", ";\n        "])), polished_1.rem(height), width ? polished_1.rem(width) : '100%');
 });
+var Content = styled_components_1["default"].div(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n"], ["\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n"])));
+var IframeElement = styled_components_1["default"].iframe(templateObject_5 || (templateObject_5 = tslib_1.__makeTemplateObject(["\n  margin: 0 auto;\n  height: 100%;\n  padding: 0;\n  width: 100%;\n  border: none;\n  background: transparent;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n"], ["\n  margin: 0 auto;\n  height: 100%;\n  padding: 0;\n  width: 100%;\n  border: none;\n  background: transparent;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n"])));
 
 var Iframe = function (_a) {
   var _b;
@@ -32,18 +34,12 @@ var Iframe = function (_a) {
     return null;
   }
 
-  var _d = _utilities_1.useDimensions({
-    liveMeasure: true
-  }),
-      ref = _d[0],
-      width = _d[1].width;
-
-  var _e = react_1["default"].useState({
+  var _d = react_1["default"].useState({
     height: data.height || exports.DEFAULT_HEIGHT,
     src: ''
   }),
-      newIframeSize = _e[0],
-      setNewIframeSize = _e[1];
+      newIframeSize = _d[0],
+      setNewIframeSize = _d[1];
 
   var locationSearch = ((_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.search) || '';
   var src = (data.src || '').replace(/{{location\.search}}/g, locationSearch).replace(/{{location\.query}}/g, locationSearch ? locationSearch.substring(1) : '');
@@ -58,14 +54,6 @@ var Iframe = function (_a) {
       return '';
     }
   }, [src]);
-  react_1["default"].useEffect(function () {
-    if (data.ratio) {
-      setNewIframeSize({
-        height: width / data.ratio,
-        src: newIframeSize.src
-      });
-    }
-  }, [data.ratio, width]);
   react_1["default"].useEffect(function () {
     if (!src) {
       return;
@@ -96,13 +84,13 @@ var Iframe = function (_a) {
   }
 
   return react_1["default"].createElement(Wrapper, {
-    ref: ref
-  }, react_1["default"].createElement(IframeElement, {
-    src: src,
-    maxWidth: data.maxWidth || undefined,
-    height: newIframeSize.height
-  }));
+    height: data.ratio ? 100 / data.ratio : newIframeSize.height,
+    width: data.ratio ? 100 : data.maxWidth,
+    hasRatio: !!data.ratio
+  }, react_1["default"].createElement(Content, null, react_1["default"].createElement(IframeElement, {
+    src: src
+  })));
 };
 
 exports["default"] = Iframe;
-var templateObject_1, templateObject_2, templateObject_3, templateObject_4;
\ No newline at end of file
+var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5;
\ No newline at end of file
diff --git a/package.json b/package.json
index 023533f1b20978f5be2d67d640cead3e41132ceb..3f3676ef2014e2bae8bead7d6b56c3f72cd62b22 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "content",
-  "version": "0.2.45",
+  "version": "0.2.46",
   "description": "",
   "main": "lib/view/index.js",
   "scripts": {
diff --git a/src/editor/widgets/Iframe/index.tsx b/src/editor/widgets/Iframe/index.tsx
index d3eaa6dbb8773f781b76540449945cb044af69a4..6e73ac62534d436ed49564931d4cb2b362791746 100644
--- a/src/editor/widgets/Iframe/index.tsx
+++ b/src/editor/widgets/Iframe/index.tsx
@@ -42,19 +42,90 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => {
   }
 
   const manualMaxWidthSet = typeof data.maxWidth !== 'undefined';
+  const manualHeightSet = typeof data.height !== 'undefined';
 
   function handleChangeManualMaxWidth(e: React.ChangeEvent<HTMLInputElement>) {
     const newValue = e.target.checked;
     const update: IData = { ...data };
     if (newValue) {
       update.maxWidth = 200;
+      delete update.ratio;
     } else {
       delete update.maxWidth;
     }
     onChange(update);
   }
 
+  function handleChangeManualHeight(e: React.ChangeEvent<HTMLInputElement>) {
+    const newValue = e.target.checked;
+    const update: IData = { ...data };
+    if (newValue) {
+      update.height = 200;
+      delete update.ratio;
+    } else {
+      delete update.height;
+    }
+    onChange(update);
+  }
+
+  const parseIframe = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
+    const value: string = e.target.value;
+    if (value.startsWith('<iframe ')) {
+      const div = document.createElement('div');
+      div.innerHTML = value.trim();
+      const elements = div.getElementsByTagName('iframe');
+      const iframe = Array.from(elements)[0];
+      const srcValue = iframe.getAttribute('src');
+      const widthValue = iframe.getAttribute('width');
+      const heightValue = iframe.getAttribute('height');
+      const newData: {
+        src?: string;
+        maxWidth?: number;
+        height?: number;
+        ratio?: number;
+      } = {};
+      if (srcValue) {
+        newData.src = srcValue;
+      }
+      if (
+        widthValue &&
+        !isNaN(Number(widthValue)) &&
+        heightValue &&
+        !isNaN(Number(heightValue))
+      ) {
+        newData.ratio = Number(
+          parseFloat(String(Number(widthValue) / Number(heightValue))).toFixed(
+            2,
+          ),
+        );
+        delete data.maxWidth;
+        delete data.height;
+      } else if (
+        widthValue &&
+        !isNaN(Number(widthValue)) &&
+        (!heightValue || isNaN(Number(heightValue)))
+      ) {
+        newData.maxWidth = Number(widthValue);
+        delete data.ratio;
+        delete data.height;
+      } else if (
+        height &&
+        !isNaN(Number(height)) &&
+        (!widthValue || isNaN(Number(widthValue)))
+      ) {
+        newData.height = Number(heightValue);
+        delete data.ratio;
+        delete data.maxWidth;
+      }
+      onChange({
+        ...data,
+        ...newData,
+      });
+    }
+  };
+
   const src = data.src || '';
+  const ratio = data.ratio;
   const maxWidth = data.maxWidth;
   const height = data.height ?? DEFAULT_HEIGHT;
 
@@ -66,6 +137,13 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => {
         <br />
         Uistite sa, že URL je správna a zobrazuje sa očakávaný obsah.
       </Message>
+      <FormField
+        rows={4}
+        placeholder='Napr. <iframe width="665" height="500" src="https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032" />'
+        onChange={parseIframe}
+        type="textarea"
+        label="Získať z iframe tagu"
+      />
       <FormField
         label="URL"
         name="src"
@@ -75,12 +153,29 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => {
         onChange={handleChangeInputValue}
         placeholder="https://"
       />
+      <FormField
+        onChange={handleChangeManualHeight}
+        label="Manuálne nastaviť výšku"
+        type="checkbox"
+        checked={manualHeightSet}
+      />
       <FormField
         onChange={handleChangeManualMaxWidth}
         label="Manuálne nastaviť maximálnu šírku"
         type="checkbox"
         checked={manualMaxWidthSet}
       />
+      {!manualHeightSet && !manualMaxWidthSet && (
+        <FormField
+          label="Pomer strán"
+          name="ratio"
+          type="number"
+          required
+          value={ratio}
+          onChange={handleChangeInputValue}
+          placeholder="Šírka/výška, napr. 1.33"
+        />
+      )}
       {manualMaxWidthSet && (
         <FormGroup>
           <Label>Maximálna šírka v pixeloch</Label>
@@ -100,24 +195,26 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => {
           />
         </FormGroup>
       )}
-      <FormGroup>
-        <Label required>Výška v pixeloch</Label>
-        <InputRange
-          type="range"
-          min={1}
-          max={5000}
-          value={height === '' ? DEFAULT_HEIGHT : height}
-          name="height"
-          onChange={handleChangeNumberInputValue}
-        />
-        <input
-          type="number"
-          value={height}
-          name="height"
-          placeholder={String(DEFAULT_HEIGHT)}
-          onChange={handleChangeNumberInputValue}
-        />
-      </FormGroup>
+      {manualHeightSet && (
+        <FormGroup>
+          <Label required>Výška v pixeloch</Label>
+          <InputRange
+            type="range"
+            min={1}
+            max={5000}
+            value={height === '' ? DEFAULT_HEIGHT : height}
+            name="height"
+            onChange={handleChangeNumberInputValue}
+          />
+          <input
+            type="number"
+            value={height}
+            name="height"
+            placeholder={String(DEFAULT_HEIGHT)}
+            onChange={handleChangeNumberInputValue}
+          />
+        </FormGroup>
+      )}
     </>
   );
 };
diff --git a/src/editor/widgets/Table/RichTextEditor/Link.js b/src/editor/widgets/Table/RichTextEditor/Link.js
index 6e2db8bdfac46fe584facbc9a78f65beb67ffbe2..58655c019a9f6883b5f2f50d5b6c136b0f4faad5 100644
--- a/src/editor/widgets/Table/RichTextEditor/Link.js
+++ b/src/editor/widgets/Table/RichTextEditor/Link.js
@@ -1,5 +1,5 @@
-import React from 'react';
 import PropTypes from 'prop-types';
+import React from 'react';
 
 export function findLinkEntities(contentBlock, callback, contentState) {
   contentBlock.findEntityRanges(character => {
diff --git a/src/editor/widgets/Table/Spreadsheet/Table/Cell.js b/src/editor/widgets/Table/Spreadsheet/Table/Cell.js
index 173d37a9694c2ead6e76b27b10b78e4ecd5027c2..bc57d6650cb5f9591689b9cf0a2091b4b84687af 100644
--- a/src/editor/widgets/Table/Spreadsheet/Table/Cell.js
+++ b/src/editor/widgets/Table/Spreadsheet/Table/Cell.js
@@ -1,9 +1,10 @@
-import { Editor, RichUtils } from 'draft-js';
+import { CompositeDecorator, Editor, EditorState, RichUtils } from 'draft-js';
 import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent';
 import { rem } from 'polished';
 import PropTypes from 'prop-types';
 import React, { Component } from 'react';
 import styled, { css } from 'styled-components';
+import Link, { findLinkEntities } from '../../RichTextEditor/Link';
 import { DataCell } from './elements';
 
 const HANDLED = 'handled';
@@ -107,11 +108,24 @@ class Cell extends Component {
       value: { __editorState },
       active,
     } = this.props;
+
+    const decorator = new CompositeDecorator([
+      {
+        strategy: findLinkEntities,
+        component: Link,
+      },
+    ]);
+
+    const editorState = EditorState.createWithContent(
+      __editorState.getCurrentContent(),
+      decorator,
+    );
+
     return (
       <Wrapper onClick={this.focus} active={active}>
         <Editor
           onFocus={this.handleFocus}
-          editorState={__editorState}
+          editorState={editorState}
           handleKeyCommand={this._handleKeyCommand}
           blockStyleFn={this.blockStyleFn}
           onChange={this.handleChange}
diff --git a/src/editor/widgets/Table/Spreadsheet/Toolbar.js b/src/editor/widgets/Table/Spreadsheet/Toolbar.js
index 0ca081d7602533b47c2502ffce6321fa42c9a58d..6ce3dd2b77e986a9d80ac8ac2b02fac21104b282 100644
--- a/src/editor/widgets/Table/Spreadsheet/Toolbar.js
+++ b/src/editor/widgets/Table/Spreadsheet/Toolbar.js
@@ -3,6 +3,8 @@ import React, { Component } from 'react';
 import styled from 'styled-components';
 import BlockAlignTool from '../RichTextEditor/tools/BlockAlignTool';
 import InlineStyleTool from '../RichTextEditor/tools/InlineStyleTool';
+import LinkRemovalTool from '../RichTextEditor/tools/LinkRemovalTool';
+import LinkTool from '../RichTextEditor/tools/LinkTool';
 import { ToolGroup } from '../RichTextEditor/tools/styles';
 import TableHeaderTool from './tools/TableHeaderTool';
 import TableSizeTool from './tools/TableSizeTool';
@@ -57,6 +59,11 @@ class Toolbar extends Component {
           />
         </ToolGroup>
 
+        <ToolGroup>
+          <LinkTool onToggle={onAction} editorState={editorState} />
+          <LinkRemovalTool onToggle={onAction} editorState={editorState} />
+        </ToolGroup>
+
         <ToolGroup>
           <BlockAlignTool
             onToggle={onAction}
diff --git a/src/editor/widgets/Table/Spreadsheet/index.js b/src/editor/widgets/Table/Spreadsheet/index.js
index b81daa18ae97e759fcc25e9c38360730feeb0b0e..1bb0c1027e2b7e3bad07e68ea2a12232ecd386e8 100644
--- a/src/editor/widgets/Table/Spreadsheet/index.js
+++ b/src/editor/widgets/Table/Spreadsheet/index.js
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
 import React, { Component } from 'react';
 import blockAlignToolAction from '../RichTextEditor/tools/BlockAlignTool/action';
 import inlineStyleToolAction from '../RichTextEditor/tools/InlineStyleTool/action';
+import linkRemovalToolAction from '../RichTextEditor/tools/LinkRemovalTool/action';
+import linkToolAction from '../RichTextEditor/tools/LinkTool/action';
 import Table from './Table';
 import Toolbar from './Toolbar';
 import tableStructureReducer from './tools/HeaderOptionsTool/action';
@@ -31,7 +33,12 @@ class Spreadsheet extends Component {
     table: [],
     selectedCell: [],
   };
-  actionHandlers = [blockAlignToolAction, inlineStyleToolAction];
+  actionHandlers = [
+    blockAlignToolAction,
+    inlineStyleToolAction,
+    linkRemovalToolAction,
+    linkToolAction,
+  ];
 
   componentDidMount() {
     const originalTable = this.getTableFromProps(this.props);
diff --git a/src/editor/widgets/Table/Spreadsheet/utilities.js b/src/editor/widgets/Table/Spreadsheet/utilities.js
index f0a359662349a7d3db1d8a18dd829f67000a8907..7b23cfcaf5a70d3ebfbf0c6dd3af41f288d50e0f 100644
--- a/src/editor/widgets/Table/Spreadsheet/utilities.js
+++ b/src/editor/widgets/Table/Spreadsheet/utilities.js
@@ -34,6 +34,19 @@ export function contentStateToHtml(contentState) {
       }
       return undefined;
     },
+    entityStyleFn: entity => {
+      const entityType = entity.get('type').toLowerCase();
+      if (entityType === 'link') {
+        const data = entity.getData();
+        return {
+          element: 'a',
+          attributes: {
+            target: data.openInNewWindow ? '_blank' : '',
+            href: data.url,
+          },
+        };
+      }
+    },
   });
 }
 
diff --git a/src/fixtures/content.fixture.ts b/src/fixtures/content.fixture.ts
index e02c56938eb5e2153c8fdc66e6b7eab5e267a500..a82d81b8863ad979e2b4ecc0e58c59717c789492 100644
--- a/src/fixtures/content.fixture.ts
+++ b/src/fixtures/content.fixture.ts
@@ -65,11 +65,16 @@ export const competitionStanding: IContent = [
 export const iframeContent: IContent = [
   {
     type: 'iframe',
-    // height: 589,
-    ratio: 1.33,
     src:
       'https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032',
-    // maxWidth: 200,
+    height: 500,
+    maxWidth: 665,
+  },
+  {
+    type: 'iframe',
+    src:
+      'https://www.ta3.com/embed/20210108-hw-d346260f-9865-4bbd-b5bf-d8403acb7f8b.html',
+    ratio: 1.78,
   },
 ];
 
@@ -222,9 +227,9 @@ export const tableContent: IContent = [
         '<p style="text-align: center"><strong>DEJISKO</strong></p>',
       ],
       [
-        '<p>1. ročník</p>',
-        '<p>1969/1970</p>',
-        '<p>Slovan Bratislava</p>',
+        '<p><a href="https://google.sk">1. ročník</a></p>',
+        '<p><a target="_blank" href="https://google.uk">1969/1970</a></p>',
+        '<p><a target="" href="https://google.de">Slovan Bratislava</a></p>',
         '<p>Dukla Banská Bystrica</p>',
         '<p>2:2, 1:0</p>',
         '',
@@ -1387,7 +1392,7 @@ const onlajnyFixtures: IContent = [
 ];
 
 export const realContent: IContent = [
-  ...onlajnyFixtures,
+  // ...onlajnyFixtures,
   // ...socialContent,
   // ...textBlockContent,
   // ...textContent,
diff --git a/src/view/widgets/Iframe/index.tsx b/src/view/widgets/Iframe/index.tsx
index f8eb6f84ec606d85c16e373636e5f7eeb422abc6..0c643723e847f7fd3446f0e124a3144f3e6a7479 100644
--- a/src/view/widgets/Iframe/index.tsx
+++ b/src/view/widgets/Iframe/index.tsx
@@ -1,16 +1,41 @@
+import { rem } from 'polished';
 import React from 'react';
 import { IWidgetIframe } from '~library';
 import styled, { css } from '~theme/styled-components';
-import { isBrowser, useDimensions } from '~utilities';
+import { isBrowser } from '~utilities';
 
 export const DEFAULT_HEIGHT = 200;
 
-const Wrapper = styled.div`
+const Wrapper = styled('div')<{
+  hasRatio: boolean;
+  width: number;
+  height: number;
+}>`
+  position: relative;
   display: flex;
+  width: 100%;
+  ${({ hasRatio, width, height }) =>
+    hasRatio
+      ? css`
+          padding-top: ${100 / (width / height)}%;
+        `
+      : css`
+          height: ${rem(height)};
+          max-width: ${width ? rem(width) : '100%'};
+        `}
+`;
+
+const Content = styled.div`
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
 `;
 
-const IframeElement = styled.iframe<{ maxWidth?: number; height: number }>`
+const IframeElement = styled.iframe`
   margin: 0 auto;
+  height: 100%;
   padding: 0;
   width: 100%;
   border: none;
@@ -20,14 +45,6 @@ const IframeElement = styled.iframe<{ maxWidth?: number; height: number }>`
   font-size: 100%;
   font-family: inherit;
   vertical-align: baseline;
-  ${({ maxWidth }) =>
-    maxWidth &&
-    css`
-      max-width: ${maxWidth}px;
-    `}
-  ${({ height }) => css`
-    height: ${height}px;
-  `}
 `;
 
 type IData = Omit<IWidgetIframe, 'type'>;
@@ -49,8 +66,6 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => {
     return null;
   }
 
-  const [ref, { width }] = useDimensions({ liveMeasure: true });
-
   const [newIframeSize, setNewIframeSize] = React.useState<INewIframeSize>({
     height: data.height || DEFAULT_HEIGHT,
     src: '',
@@ -75,12 +90,6 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => {
     }
   }, [src]);
 
-  React.useEffect(() => {
-    if (data.ratio) {
-      setNewIframeSize({ height: width / data.ratio, src: newIframeSize.src });
-    }
-  }, [data.ratio, width]);
-
   React.useEffect(() => {
     if (!src) {
       return;
@@ -112,12 +121,14 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => {
   }
 
   return (
-    <Wrapper ref={ref}>
-      <IframeElement
-        src={src}
-        maxWidth={data.maxWidth || undefined}
-        height={newIframeSize.height}
-      />
+    <Wrapper
+      height={data.ratio ? 100 / data.ratio : newIframeSize.height}
+      width={data.ratio ? 100 : data.maxWidth}
+      hasRatio={!!data.ratio}
+    >
+      <Content>
+        <IframeElement src={src} />
+      </Content>
     </Wrapper>
   );
 };